如何取消导入Python模块?
我正在开发一个应用程序,这个程序需要从多个模块(.py 文件)中提取一些元数据(比如作者、版本等等),然后把这些信息展示出来。用户可以选择一个脚本,然后执行这个脚本。(新的脚本可以添加,旧的脚本可以像插件一样从目标文件夹中移除。)
首先,我导入一个脚本,然后提取它的元数据,接着再处理下一个脚本。但我想要在用户选择的脚本之外,把其他所有模块都“去掉”。
我该怎么实现这个呢?
我尝试了这些
1. del module
2. del sys.modules['module']
但后面的方案没有成功。我试过用 #python,得到的回答是“去掉模块”并不好,但我想知道有没有更好的方法来实现这个。任何想法或建议都很有帮助。
4 个回答
我最近发现了这个帖子 https://www.geeksforgeeks.org/reloading-modules-python/,所以对于 Python 3.4 或更高版本,可以使用下面的代码:
import importlib
importlib.reload(module)
建议:使用 __import__
动态导入你的模块
例如:
module_list = ['os', 'decimal', 'random']
for module in module_list:
x = __import__(module)
print 'name: %s - module_obj: %s' % (x.__name__, x)
这将产生:
name: os - module_obj: <module 'os' from '/usr/lib64/python2.4/os.pyc'>
name: decimal - module_obj: <module 'decimal' from '/usr/lib64/python2.4/decimal.pyc'>
name: random - module_obj: <module 'random' from '/usr/lib64/python2.4/random.pyc'>
不过,这样做并不会真的把它从模块注册表中移除。下次再导入的时候,它不会重新读取包/模块文件,也不会执行它。要做到这一点,你可以简单地把上面的代码片段修改成这样:
import sys
module_list = ['os', 'decimal', 'random', 'test1']
for module_name in module_list:
x = __import__(module_name)
print 'name: %s - module_obj: %s' % (x.__name__, x)
del x
sys.modules.pop(module_name)
我觉得这篇帖子应该能帮到你。
为了确保这些信息的可用性(以防链接失效或其他类似情况),下面是来自tutor邮件列表的原始信息:
在2006年8月14日,Dick Moores写道:
其实,我的问题是,使用IDLE导入模块和初始化变量后,如何在不关闭和重新打开IDLE的情况下将其恢复到初始状态。
举个例子,在我做了
>>> import math, psyco >>> a = 4**23
之后,如何在不关闭IDLE的情况下清除这些内容?(我以前知道怎么做,但我忘了。)
嗨,Dick,
通常,这涉及到从“模块注册表”中删除模块,并在代码中移除对它的引用。如果你有一个使用得非常频繁的模块(比如一个在每个模块中都导入了配置参数的模块),那么你还需要额外一步,从每个模块中删除它。此外,如果你使用了“from psyco import ...”,那么你将无法轻易释放这个模块和对它的引用(这到底是来自哪个模块,还是从第三个模块导入的?见“如果小心:下面的代码)。
下面的函数通过名称从Python解释器中删除一个模块,“paranoid”参数是一个变量名的列表,用于从其他模块中删除(假设这些变量会随着模块一起被删除)。使用“paranoid”参数时要非常小心;如果你的函数和类在不同模块中有相同的名称,可能会导致解释器出现问题。一个常见的情况是“error”用于异常处理。很多库都有一个叫“error”的“通用”异常。如果你也把你的异常命名为“error”,并决定把它包含在“paranoid”列表中……那就会影响到很多其他的异常对象。
def delete_module(modname, paranoid=None):
from sys import modules
try:
thismod = modules[modname]
except KeyError:
raise ValueError(modname)
these_symbols = dir(thismod)
if paranoid:
try:
paranoid[:] # sequence support
except:
raise ValueError('must supply a finite list for paranoid')
else:
these_symbols = paranoid[:]
del modules[modname]
for mod in modules.values():
try:
delattr(mod, modname)
except AttributeError:
pass
if paranoid:
for symbol in these_symbols:
if symbol[:2] == '__': # ignore special symbols
continue
try:
delattr(mod, symbol)
except AttributeError:
pass
然后你应该可以像这样使用:
delete_module('psyco')
或者
delete_module('psyco', ['Psycho', 'KillerError'])
# only delete these symbols from every other module
# (for "from psyco import Psycho, KillerError" statements)
-Arcege