如何取消已导入的Python模块?

119

我对NumPy / SciPy相当新。但是这些天,我已经开始积极使用它来进行数值计算,而不是使用Matlab。

对于一些简单的计算,我只是在交互模式下进行而不写脚本。在这种情况下,是否有任何方法可以取消导入已经导入的一些模块?在编写Python程序时可能不需要取消导入,但在交互模式下,则需要取消导入。


但是命名空间?可能有外部来源?需要深度扫描... - dsgdfg
说句题外话,您不能重启CLI来重置导入吗? - Frank V
为什么你会需要在代码中取消导入一个模块?并不是说你不需要,只是我想不到有什么理由... - lollercoaster
您想查看这个答案:https://dev59.com/knRC5IYBdhLWcg3wAcXU - daf
1
https://dev59.com/X1gQ5IYBdhLWcg3wLg45 是使用 del sys.modules['foo'] 的解决方案,但需要注意一些限制。 - Robert Fleming
显示剩余2条评论
4个回答

146

如果你导入了某个东西,就没有办法再卸载它。Python会在缓存中保留这个模块的副本,所以下一次导入它时,就不需要重新加载和初始化了。

如果你只想失去访问权限,可以使用del


import package
del package

注意,如果您重新导入该包,则将使用模块的缓存副本。

如果您想使模块的缓存副本无效,以便在重新导入时重新运行代码,可以使用 sys.modules.pop,如@DeepSOIC's answer 中所述。

如果您对软件包进行了更改并希望查看更新内容,则可以使用 reload。请注意,在某些情况下,这种方法不起作用,例如如果导入的软件包还需要重新加载它所依赖的软件包。在依赖此功能之前,请阅读相关文档。

对于Python版本2.7及以下,reload是一个内置函数:

reload(package)

Python 3.0到3.3版本可以使用imp.reload函数:

import imp
imp.reload(package)

对于 Python 版本 3.4 及以上,您可以使用 importlib.reload

import importlib
importlib.reload(package)

1
这会清除可用函数名称的字典吗? - MadPhysicist
@MadPhysicist 不确定你在问什么。 - Mark Ransom
我想我要问的是这样的。假设你执行了 import numpy as np,然后又执行了 np.pi = 2。那么我该如何在 Python 中将其重置为 n.pi = 3.14 .. 的状态或者还没有导入 numpy 的状态呢?简而言之,是否可以完全撤销导入操作而无需重新加载 Python 或控制台? - MadPhysicist
@MadPhysicist 我会期望 reload 重新初始化模块的整个内容,撤销您对其所做的任何更改。 您试过了吗? - Mark Ransom
该方法可能无法覆盖其他模块对重新加载的模块的引用。请参阅 https://dev59.com/knRC5IYBdhLWcg3wAcXU#61617169 以获取解决方案。 - EZLearner

39
当你导入一个模块时,Python会查看sys.modules字典中是否存在该模块。如果不存在,则运行该模块,并将生成的模块对象放入sys.modules中。
因此,要取消导入一个模块,可以使用:
import sys
sys.modules.pop('your_module_name_here')

下次导入该模块时,Python会重新执行该模块。但是,在所有已导入该模块的其他加载模块中,旧代码仍将被使用,因为它们仍然持有对旧模块对象的引用。其他答案中解释了reload函数可以通过更新模块对象而不是创建全新的模块对象来解决这种情况。但是它无法帮助from your_module import some_function类型的导入。

4
我认为这个答案比“del”更好,因为它会使导入缓存失效,在这种情况下我几乎总是想要这样做... - maxymoo
1
@maxymoo 你可能需要两者都做。Python很乐意在导入新模块后仍保留旧版本,只要它还有引用存在。 - Mark Ransom

16

虽然在Python中你不必担心“取消导入”一个模块,但通常你可以使用del来简单地减少对已经import的模块或函数的引用:

>>> import requests
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'readline', 'requests', 'rlcompleter']
>>> del requests
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'readline', 'rlcompleter']
>>>

请注意,我建议您不要担心这个问题,因为未使用的导入的开销几乎可以忽略不计——在 sys.modules 中遍历一个额外的条目与 del some_module 给您带来的虚假安全感相比微不足道(考虑一下如果 __init__ 进行了一些设置或者您运行了 from X import *)。

Python如何取消导入pyd模块? - CS QGB

6

我的建议是,你需要找到所有与该模块相关的/子级别的 import,才能成功地将它们移除。

package_name = your_package_name
loaded_package_modules = [key for key, value in sys.modules.items() if package_name in str(value)]
for key in loaded_package_modules:
        print(key)
        del sys.modules[key]

Python如何取消导入pyd模块? - CS QGB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接