zoukankan      html  css  js  c++  java
  • Python实践:模块自动重载

    一、概述

    开发Web程序时,通常会采用本地服务器进行调试,但如果代码有变动,就需要重启服务器。开发过程中修改代码是经常的事,不断地重启服务器既麻烦又耗时。因此为了避免这种笨拙的行为,在流行的Web框架中,都提供了 模块自动重载 的功能:不用重启服务器,自动重新加载有变动的模块。

    自动 的方式有很多,具体跟Web框架的实现强相关。像web.py中就是通过每次处理请求时都尝试重载来模拟自动,而flask中则是使用独立线程来完成的。简单起见,本文的测试代码中采用while循环(独立进程)来实现自动。

    二、思路

    遍历已经加载的所有模块,查看每个模块的对应文件的最近修改时间,如果时间有变化,则重新加载该模块。

    三、实现

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    """Reload modules if modified
    
    usage:
        python reloader.py [test_module_name]
    """
    
    import sys
    import os
    
    mtimes = {}
    
    def do_reload(handler=None):
        """Reload modules if modified
        """
        for module in sys.modules.values():
            # get filename
            filename = getattr(module, '__file__', None)
            if not (filename and os.path.isfile(filename)):
                continue
    
            # handle python file extensions
            # for more details about this topic,
            # see http://stackoverflow.com/questions/8822335/what-does-python-file-extensions-pyc-pyd-pyo-stand-for
            if filename[-4:] in ('.pyc', '.pyo', '.pyd'):
                filename = filename[:-1] # get the '.py' file
    
            # get the time of most recent content modification
            try:
                mtime = os.stat(filename).st_mtime
            except OSError:
                continue
    
            # reload `module` if it's modified
            old_time = mtimes.get(module)
            if old_time is None: # the first time in this function, just record mtime
                mtimes[module] = mtime
            elif old_time < mtime: # `module` is modified
                try:
                    reload(module)
                    mtimes[module] = mtime
    
                    if handler: # call handler() if necessary
                        handler(module)
    
                except ImportError:
                    pass
    
    if __name__ == '__main__':
        if len(sys.argv) != 2:
            sys.stderr.write(__doc__)
            sys.exit(1)
    
        test_module_name = sys.argv[1]
        import importlib
        try:
            importlib.import_module(test_module_name)
        except ImportError, e:
            print(str(e))
            sys.exit(1)
    
        import time
        def handler(module):
            print(dir(module))
    
        print('start reloading module `%s` automatically...' % test_module_name)
        while True:
            try:
                do_reload(handler)
                time.sleep(2)
            except KeyboardInterrupt:
                break
    

    四、测试

    1、开启自动重载(终端1)

    $ touch testmod.py
    $ python reloader.py testmod
    start reloading module `testmod` automatically...
    

    2、修改模块(终端2)

    $ vi testmod.py
    ...
    

    3、查看实时输出(终端1)

    一旦对testmod.py有修改保存,终端1中会立即打印出模块testmod的当前所有属性。当然,也可以修改handler来实现其他的处理方式。

    五、参考源码

    (1)web.py的Reloader

    (2)werkzeug的_reloader_stat_loop

  • 相关阅读:
    利用mybatis-generator自动生成代码
    gradle安装
    有关﹤![CDATA[ ]]> 说明
    mysql时间字段转换为毫秒格式
    string 与BigDecimal互转
    VLOOKUP多条件查找不使用辅助列
    BIEE-CSS样式大全
    VBA【遍历每个工作表并将工作表表名赋予B2单元格】
    深入理解公式{1,0}的用法
    DB2解锁
  • 原文地址:https://www.cnblogs.com/russellluo/p/3388232.html
Copyright © 2011-2022 走看看