• 不重启程序使用最新版package


    相信很多使用python者都对reload方法比较熟悉了,通过不间断地reload可以实现某一module的热更新,主要就能在不重启应用的情况下实现部分模块的更新。但这种方法仅限于reload当前工作目录下的module,对于通过setuptools安装的egg包就不灵了,具体分析如下:
    (1)python 的import或者reload都是根据sys.path来进行查找相关module的,找到第一个匹配的module之后就进行加载然后退出此操作
    (2)sys.path是有一定的顺序的
    (3)通过setuptools 的easy_install进行安装的package,每个版本都保留在site-packages中
    (4)sys.path正常情况下只有在python进程启动的时候进行赋值
    (5)通过easy_install进行安装后easy_install.pth中记录的已经是最新版的package,但如果此时没有重启python进程,则sys.path中记录的还是原有的package位置,这时reload的话首先找到的还是老版本的package,也就是说新版并未生效
    怎么解决这一问题?怎么在不重启程序的情况下使用新版的package?
    通过研究python代码可以知道,python在启动的时候会加载 site.py,site.py中有一个main()函数负责对sys.path进行赋值操作,为实现我们在不重启程序就能使用最新版package的目的,可以通过显式调用site.py中的main()函数来操作,具体代码如下:

    # -*- coding: utf-8 -*-
    
    import sys
    import site
    import time
    import os.path
    import copy
    
    def reload_module(module_str):
        '''
        reload module
        '''
        paths_old = copy.deepcopy(sys.path)
        # invoke site.main to get updated sys.path
        site.main()
        paths_new = copy.deepcopy(sys.path)
        updated = []
        # parse updated packages
        for item in paths_new[len(paths_old):]:
            _, egg_name = os.path.split(item)
            # egg_name like this : requests-1.1.0-py2.7.egg
            # parse real package name
            if len(egg_name) > 0:
                package_name = egg_name.split('-')[0]
                updated.append(package_name)
        # erase old version packages
        sys.path = []
        for item in paths_new[:len(paths_old)]:
            _, egg_name = os.path.split(item)
            if len(egg_name) > 0:
                package_name = egg_name.split('-')[0]
                if package_name in updated:
                    # a new version is already exists, so erase the old one
                    pass
                else:
                    sys.path.append(item)
        # append the updated
        sys.path.extend(updated)
        if sys.modules.has_key(module_str):
            print 'need reload'
            reload(sys.modules[module_str])
        else:
            print 'need import'
            try:
                exec 'import %s' %module_str
            except Exception, e:
                print e
            
    
    def main():
        import requests
        while True:
            time.sleep(2)
            reload_module('requests')
            print requests.__version__
    
    if __name__ == '__main__':
        main()

    如果在程序运行过程中安装了新版的requests,则程序运行结果如下所示:
    C:UsersJerryKwanDesktop>python get_current_version.py
    need reload
    1.2.0
    need reload
    1.2.0
    need reload
    1.2.0
    need reload
    1.2.0
    need reload
    1.2.3
    need reload
    1.2.3
    need reload
    1.2.3

  • 相关阅读:
    PHP之十六个魔术方法详解
    PHP之十六个魔术方法详解
    让Docker容器使用静态独立的外部IP(便于集群组建)
    桥接和nat模式区别
    使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署
    docker gitlab
    docker gitlab安装
    docker ui管理工具
    docker 批量删除容器
    Scrapy设置代理
  • 原文地址:https://www.cnblogs.com/Jerryshome/p/3506914.html
Copyright © 2020-2023  润新知