如何取消导入Python模块?

43 投票
4 回答
45869 浏览
提问于 2025-04-15 15:38

我正在开发一个应用程序,这个程序需要从多个模块(.py 文件)中提取一些元数据(比如作者、版本等等),然后把这些信息展示出来。用户可以选择一个脚本,然后执行这个脚本。(新的脚本可以添加,旧的脚本可以像插件一样从目标文件夹中移除。)

首先,我导入一个脚本,然后提取它的元数据,接着再处理下一个脚本。但我想要在用户选择的脚本之外,把其他所有模块都“去掉”。

我该怎么实现这个呢?

我尝试了这些

1. del module
2. del sys.modules['module']

但后面的方案没有成功。我试过用 #python,得到的回答是“去掉模块”并不好,但我想知道有没有更好的方法来实现这个。任何想法或建议都很有帮助。

4 个回答

7

我最近发现了这个帖子 https://www.geeksforgeeks.org/reloading-modules-python/,所以对于 Python 3.4 或更高版本,可以使用下面的代码:

import importlib
importlib.reload(module) 
7

建议:使用 __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)
23

我觉得这篇帖子应该能帮到你。

为了确保这些信息的可用性(以防链接失效或其他类似情况),下面是来自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

撰写回答