python reload()没有任何效果?

2024-10-03 06:23:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个糖化酶.pypyspark目录中的文件。在REPL中,我尝试重新加载它:

>>> reload(pyspark.hbase)
<module 'pyspark.hbase' from '/shared/hwspark2/python/pyspark/hbase.py'>
>>> from pyspark.hbase import *
>>> # run the code .. latest changes not apparent..

没有错误。。但是,类的定义没有更新,新的print语句没有出现就证明了这一点。在

在退出解释器并重新加载模块后,可以看到更新。然而,即使在调用reload之后,对该模块的任何进一步更改都不可见。在


Tags: 模块文件frompyimport目录replreload
2条回答

这个问题还不完全清楚,但我认为你误解了^{}的作用。在

它重新导入模块,包括其中定义的所有新类对象,并更改sys.modules[name]以引用新的模块对象,还将名称复制到全局变量中。在

但这就是一切。它不会自动找到对旧模块的所有引用,更不用说旧模块中定义的任何内容,等等,并将它们全部修复为引用替换版本。(怎么可能?新模块中甚至可能没有替代版本。因此,如果您的值是由旧代码计算的,并且计算方式不同,那么会怎样;它必须重新运行导入模块后所做的所有操作。)

文档(上面的链接)用不同的术语解释了它,但是让我们把它具体化,这样我可以更直接地解释它。在

创建此文件:

# mod.py
class Spam(object):
    def eggs(self):
        print('spam spam spam spam')

现在:

^{pr2}$

现在编辑它:

# mod.py
class Spam(object):
    def eggs(self):
        print('out of spam!!!')

>>> reload(mod)
>>> spam.eggs()
spam spam spam spam
>>> morespam = mod.Spam()
>>> morespam.eggs()
out of spam!!!
>>> type(spam) is type(morespam)
False

当您通过调用mod.Spam()来创建spam,它在全局中查找'mod',然后在结果模块中查找{},然后调用其构造函数和初始值设定项,给您一个对象,该对象的__class__是对该mod.Spam类的引用。在

当您调用spam.eggs()时,Python在全局字典中查找'spam',在spam对象的字典中查找{},否则,在spam.__class__对象的字典中查找{}。我们知道,这就是mod.Spam对象,它有一个eggs方法,因此被调用。在

现在,在我们reload(mod)之后,有一个名为'mod'的新对象,它有一个名为'Spam'的新类作为成员。但是旧的modmod.Spam对象,以及您的spam-仍然存在。而现有的spam在其__class__中仍然引用了旧的{}。因此,当您第二次调用spam.eggs()时,与之前完全相同的情况发生。Python将'spam'作为全局查找,首先在spam中查找'eggs',然后在{}中查找{},找到与之前相同的类,并调用与之前相同的函数。在

当我们再次调用mod.Spam()来构造morespam时,现在它在全局中查找'mod',并找到新的{}。然后在该模块中查找'Spam',并找到新类。因此,我们有一个实例,它的__class__是新的mod.Spam。当我们调用它的eggs方法时,会发生与上面相同的情况,但现在调用的是新函数。在


使用from mod import *而不是{}会使事情变得更难理解,但基本思想是相同的。from mod import *不会将mod放入全局变量,而是将其所有非私有全局变量(在mod.__all__中列出的任何内容,或者,如果不存在这样的内容,mod中不以一个下划线开头的任何内容)复制到全局变量。因此,reload创建一个新的模块对象,第二个from mod import *将新模块的所有非私有全局变量复制到全局变量中,替换旧的全局变量。但是您的spam实例仍然是旧的Spam的实例,而不是新实例。在

脑海中浮现出三种可能性(一种是@abarner的):

  • pyspark.hbase有一个__all__,而您尝试使用的类不在其中
  • pyspark.hbase没有__all__,但类名/函数等以_开头。在
  • 重新加载后不会重新创建类实例,因此它们仍然绑定到旧模块的类。在

__all__用作模块定义其官方API的一种方式。它还用于提供在发出from ... import *时要导入的名称列表。如果未定义__all__,那么在该模块上使用from ... import *时,将加载该模块中任何不以_开头的名称。在

无论是否定义了__all__,您始终可以通过直接请求来显式加载模块中定义的任何名称:

from xyz import _private

{12>将加载到你的命名空间中。在

相关问题 更多 >