我正在编写一个应用程序,它必须从几个模块(.py文件)中获取元数据(author,version..etc)并显示它们。用户选择脚本并执行脚本。 (可以添加新脚本,并且可以像插件系统一样从目标文件夹中添加旧脚本)。
首先我导入一个脚本,然后取出元数据,接下来我就去了。 但我想取消导入所有其他模块,除了用户选择的模块。
我该如何实现?
我试过这些
1. del module
2. del sys.modules['module']
后者不起作用。我试过#python并得到了一个解决方案,即取消导入模块并不好,但我想知道一种干净的方法来实现它。任何想法/建议都会有所帮助。
答案 0 :(得分:18)
我认为this post可以帮助你
编辑: 为确保此信息的可用性(如果链接死亡或类似的情况),我将在tutor mailing list包含原始邮件:
在8/14/06,Dick Moores写道:
实际上,我的问题是,在使用IDLE进行一些导入之后 模块和变量的初始化,如何将它返回给它 初始条件没有关闭并重新打开它。
所以,例如在我完成之后
>>> import math, psyco >>> a = 4**23
如何在不关闭IDLE的情况下擦除它们? (我曾经知道如何,但我已经忘记了。)
嗨迪克,
通常这需要从“模块注册表中删除并删除 在代码中引用它。如果您有一个真正使用良好的模块(如 一个配置参数导入每个模块),那么你将有一个 从每个模块中删除它的附加步骤。另外,如果你有用 “来自psyco import ...”,那么你将无法释放模块和 轻松引用模块(是从该模块引入,还是从中导入) 第三个模块?看“如果偏执狂:代码如下”。
下面的函数从Python解释器中按名称删除模块 “paranoid”参数是要从其他所有名称中删除的变量名称列表 模块(假设与模块一起删除)。要非常小心 偏执狂的param;如果您的翻译可能会给您的口译员带来麻烦 函数和类在不同的模块中命名相同。一个常见的 这种情况的出现是例外的“错误”。很多图书馆都有一个 模块中称为“错误”的“catch-all”异常。如果你也命名了你的 异常“错误”并决定将其包括在偏执列表中......那里 去了很多其他异常对象。
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
答案 1 :(得分:6)
建议:使用__import__
E.g。
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)
答案 2 :(得分:2)
我知道这篇文章已经过时但我刚刚遇到这个问题并且在过去的几天里一直在努力反对它。现在我得出了一个可以完美解决这个问题的结论。请参阅下面的示例代码:
try:
theMod = sys.modules['ModNeedToBeDel']
except:
theMod = None
if theMod:
del sys.modules['ModNeedToBeDel']
#The extra try/except below is because I implemented the block in a module of a sub-package; this ModNeedToBeDel in my case was imported either by the toppest level Main code, or by the other sub-package modules. That's why I need two different try/except.
try:
theMod = sys.modules['UpperFolder.ModNeedToBeDel']
except:
theMod = None
if theMod:
del sys.modules['UpperFolder.ModNeedToBeDel']
import ModNeedToBeDel # or UpperFolder.ModNeedToBeDel here
请注意,del sys.modules[theMod]
无法使用,因为它只会删除引用,而不是实际的ModNeedToBeDel
。
希望这可以帮助某些人,这样他们就不会在这个问题上挣扎好几天了!
答案 3 :(得分:1)
我最近发现了这篇文章https://www.geeksforgeeks.org/reloading-modules-python/,因此对于Python 3.4或更高版本使用
import importlib
importlib.reload(module)