【问题标题】:How to unimport a python module which is already imported?如何取消导入已经导入的python模块?
【发布时间】:2015-08-26 18:33:31
【问题描述】:

我对 NumPy/SciPy 很陌生。但是这些天来,我开始非常积极地使用它来进行数值计算,而不是使用 Matlab。

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

【问题讨论】:

  • 但是命名空间?也许有外部来源?需要深度扫描...
  • 为了论证,当您需要重置导入时,是否有无法重新启动 CLI 的原因?
  • 为什么需要取消导入模块?不是说你没有,我只是想不出一个理由......
  • 如果要分配不同的名称来处理命令冲突,可以使用 import-as 语法。例如:import numpy as np
  • stackoverflow.com/questions/43181440/… 是一个使用del sys.modules['foo'] 的带有警告的解决方案。

标签: python python-import


【解决方案1】:

一旦导入,就无法卸载它。 Python 将模块的副本保存在缓存中,因此下次导入它时不必重新加载和重新初始化它。

如果您只需要失去对它的访问权限,您可以使用del

import package
del package

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

如果您想使模块的缓存副本无效,以便在重新导入时重新运行代码,您可以按照@DeepSOIC 的回答使用sys.modules.pop

如果您对软件包进行了更改并且想要查看更新,您可以reload 它。请注意,这在某些情况下不起作用,例如,如果导入的包还需要重新加载它所依赖的包。在依赖此之前,您应该阅读相关文档。

对于最高 2.7 的 Python 版本,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)

【讨论】:

  • 这会清除包含可用函数名称的字典吗?
  • @MadPhysicist 不确定你在问什么。
  • 我想我要问的是这个。假设您先执行import numpy as np,然后执行np.pi = 2。如何将 Python 中的内容重置为 n.pi = 3.14 .. 状态或尚未导入 numpy 的状态。简而言之,可以在不重新加载 Python 或控制台的情况下完全撤消导入吗?
  • @MadPhysicist 我希望reload 会重新初始化模块的全部内容,撤消您对其所做的任何更改。你试过了吗?
  • 此方法可能不会覆盖其他模块对重新加载模块的引用。请参阅stackoverflow.com/a/61617169/2642356 以获得解决方案。
【解决方案2】:

当你导入一个模块时,Python 会查看这个模块是否在 sys.modules 字典中。如果没有,它会运行模块,并将生成的模块对象放入sys.modules

因此,要取消导入模块,可以使用

import sys
sys.modules.pop('your_module_name_here')

下次导入时,python会重新执行该模块。但是,在所有其他已导入模块的已加载模块中,仍将使用旧代码,因为它们仍保留对旧模块对象的引用。 reload 其他答案中解释的函数通过更新模块对象而不是创建一个全新的对象来帮助解决这种情况。但它对 from your_module import some_function 导入样式没有帮助。

【讨论】:

  • 我认为这是比del 更好的答案,因为它使导入缓存无效,这是我在这类情况下几乎总是想要的...
  • @maxymoo 你可能需要同时做这两个。 Python 非常乐意保留旧版本的模块,即使在您导入新版本后,只要对它的引用存在。
【解决方案3】:

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

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

请注意,我建议不要担心这一点,因为未使用的导入的开销几乎是微不足道的——与 del some_module 的错误安全性相比,遍历 sys.modules 中的一个额外条目是微不足道的(考虑如果__init__ 进行了一些设置,或者您运行了 from X import *)。

【讨论】:

    【解决方案4】:

    我的建议是,您必须找到所有相关/子 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]
    

    【讨论】:

      猜你喜欢
      • 2011-11-06
      • 2014-03-29
      • 1970-01-01
      • 2011-08-17
      • 2018-01-21
      • 1970-01-01
      • 2015-03-05
      • 2016-10-08
      • 2015-10-06
      相关资源
      最近更新 更多