本文已参加「新人创造礼」活动,一同敞开掘金创造之路。
前言
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()函数,被删除的办法不会剔除。