• python笔记73动态导入模块import_module 和 重载reload 上海


    前言

    python动态加载import_module 和 重载reload 的使用
    python环境:V3.6.x

    import_module

    当我们在运行一段程序,根据需要动态加载一个模块,调用里面的方法时,除了平台使用的import module,也可以在代码里面用到import_module方法。
    比如我有个模块 yoyo.py,里面写了个函数

    def fun1():
        return "hello world"
    
    
    def fun2():
        return "上海-悠悠"
    

    a.py 需要加载yoyo.py模块(2个文件在同一层级)

    import importlib
    import inspect
    
    
    # 动态导入模块
    m = importlib.import_module('yoyo')
    print(m)  # module object
    
    # 调用fun1
    print(m.fun1())  # hello world
    
    # 获取模块全部函数
    items = inspect.getmembers(m, inspect.isfunction)
    print(dict(items))
    # {'fun1': <function fun1 at 0x0000015CEAEA0DC0>, 'fun2': <function fun2 at 0x0000015CEAEEA670>}
    

    运行结果:

    <module 'yoyo' from 'D:\\demo\\demo\\yoyo.py'>
    hello world
    {'fun1': <function fun1 at 0x0000015CEAEA0DC0>, 'fun2': <function fun2 at 0x0000015CEAEEA670>}
    

    动态更新模块

    前面importlib.import_module()导入模块是没有问题的,但是如果在执行的过程中 yoyo.py 模块发生了改变,会无法加载到最新的方法。
    可以在python交互环境测试次问题

    D:\demo\demo>python
    Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import importlib
    >>> m = importlib.import_module('yoyo')
    >>> m
    <module 'yoyo' from 'D:\\demo\\demo\\yoyo.py'>
    >>> m.fun1()
    'hello world'
    >>> m.fun2()
    '上海-悠悠'
    >>>
    

    当我在yoyo.py模块新增一个fun3()函数时,yoyo.py内容如下

    def fun1():
        return "hello world"
    
    
    def fun2():
        return "上海-悠悠"
    
    
    def fun3():
        return "hello yoyo"
    

    此时继续在上面交互环境操作,调用fun3()方法

    >>> m.fun3()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'yoyo' has no attribute 'fun3'
    >>>
    

    于是会看到新增的函数是无法调用的,因为在前面已经导入了模块,模块里面的2个函数,已经被加载进去了,后面模块更新的内容是不会自动更新的。
    那么有没什么办法,可以在新增方法后,重新让系统加载一次模块呢?这里可以用到reload() 方法,重载模块

    reload() 重载模块

    接着刚才的报错,使用reload()重载模块

    >>> from importlib import reload
    >>> new = reload('yoyo')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "E:\python36\lib\importlib\__init__.py", line 139, in reload
        raise TypeError("reload() argument must be a module")
    TypeError: reload() argument must be a module
    >>>
    

    直接写模块名称会出现报错:reload() argument must be a module

    看下reload()的相关源码说明:传的module参数必须在使用之前被成功导入过。

    def reload(module):
        """Reload the module and return it.
    
        The module must have been successfully imported before.
    
        """
        if not module or not isinstance(module, types.ModuleType):
            raise TypeError("reload() argument must be a module")
        try:
            name = module.__spec__.name
        except AttributeError:
            name = module.__name__
    

    module参数可以通过sys模块获取到模块对象 sys.modules['yoyo']

    >>> import sys
    >>> sys.modules['yoyo']
    <module 'yoyo' from 'D:\\demo\\demo\\yoyo.py'>
    >>> new = importlib.reload(sys.modules['yoyo'])
    >>> new.fun3()
    'hello yoyo'
    >>> new.fun1()
    'hello world'
    >>> new.fun2()
    '上海-悠悠'
    

    于是就可以成功调用到新增的fun3()方法

    更新方法和删除方法

    如果更新了方法里面代码,fun3()改成返回"123456"

    def fun3():
        return "123456"
    

    重新reload()后,代码也会更新

    >>> new = importlib.reload(sys.modules['yoyo'])
    >>> new.fun3()
    '123456'
    

    如果把func3()删除了呢?

    >>> new = importlib.reload(sys.modules['yoyo'])
    >>> new.fun3()
    '123456'
    

    重新reload()后,依然可以调用到fun3()函数,被删除的方法不会剔除。

  • 相关阅读:
    Poj2155Matrix二维线段树
    二维树状数组模板
    PAT-1014 Waiting in Line (30 分) 优先队列
    PAT-1012 The Best Rank (25 分) 查询分数对应排名(包括并列)
    PAT-1003 Emergency (25 分) 最短路最大点权+求相同cost最短路的数量
    PAT-1001 A+B Format (20 分) 注意零的特例
    利用requests和BeautifulSoup爬取菜鸟教程的代码与图片并保存为markdown格式
    菜鸟教程上的设计模式代码合集
    用python将项目中的所有代码(或txt)合并在一个文件中
    POJ 2485 Prim 找最长的边
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/16089824.html
Copyright © 2020-2023  润新知