包上的`del`有某种记忆

Agu*_*guy 43 python packages ipython del python-3.x

del似乎有一些困扰我的记忆.请参阅以下内容:

In [1]: import math

In [2]: math.cos(0)
Out[2]: 1.0

In [3]: del math.cos

In [4]: math.cos(0)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-9cdcc157d079> in <module>()
----> 1 math.cos(0)

AttributeError: module 'math' has no attribute 'cos'
Run Code Online (Sandbox Code Playgroud)

精细.让我们看看如果删除整个数学包会发生什么:

In [5]: del math

In [6]: math.cos(0)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-9cdcc157d079> in <module>()
----> 1 math.cos(0)

NameError: name 'math' is not defined
Run Code Online (Sandbox Code Playgroud)

所以现在数学本身就像预期的那样消失了.

现在让我们再次导入数学:

In [7]: import math

In [8]: math.cos(0)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-9cdcc157d079> in <module>()
----> 1 math.cos(0)

AttributeError: module 'math' has no attribute 'cos'
Run Code Online (Sandbox Code Playgroud)

因此,交互式python以某种方式记住,即使在我们删除了整个数学包并再次导入之后,math.cos也被删除了.

python在哪里保留这些知识?我们可以访问吗?我们可以改变它吗?

dec*_*eze 62

一个包只从磁盘读取一次,然后作为可变单例存储在内存中.第二次导入它时,你会获得与先前导入的完全相同的单例,并且它仍然缺少它cos.del math只是删除它的本地名称,它不会从Python整体"unmport"包.

  • 要再添加一个细节 - 第二个`import math`将在`sys.modules`中查找已加载(并且仍在变异)的模块,并跳过任何再次从磁盘加载的尝试.您可以尝试从`sys.modules`中删除它以强制重新加载,或使用`importlib`等. (11认同)

Jea*_*bre 23

我会说这个包仍然被视为已导入.所以import math再次表演只是重新声明名称,但旧的内容.

您可以使用reload以确保您的模块再次完整,除了某些版本的python还需要删除该条目sys.modules,这使得使用reload冗余:

import math
del math.cos
del math
sys.modules.pop("math")   # remove from loaded modules
import math
print(math.cos(0))  # 1.0
Run Code Online (Sandbox Code Playgroud)

(各种python版本之间的差异,reloadimport在后续问题中讨论:importlib.reload应该在Python 3.6中恢复已删除的属性吗?)


Rem*_*ich 15

del math根本不删除包,只删除当前模块中的本地名称 math.

与任何其他对象一样,如果对数学模块的任何其他引用存在于任何地方,则它将保留在内存中.

特别是,sys.modules它始终是所有已加载模块的字典,因此至少在那里总是有一个参考.

编辑:但有一种方法可以实际重新加载模块,imp.reload.

不幸的是我无法让它适用于这种情况,重载需要随机模块(可能是创建编译的Python文件的某些部分),随机模块需要math.cos,它已经消失了.即使random首先导入也没有错误,但math.cos不会再出现; 我不知道为什么,也许是因为它是一个内置模块.