我在pyspark目录中有一个hbase.py文件。在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..
没有错误..但是,类的定义没有更新 - 正如新的印刷语句没有出现所证明的那样。
退出解释器并重新加载模块后,可以看到更新。然而,即使在重新加载后,模块的任何进一步更改也都不可见。
答案 0 :(得分:2)
问题并不完全清楚,但我认为你误解了reload
的所作所为。
它重新导入模块,包括其中定义的所有新类对象,并更改sys.modules[name]
以引用该新模块对象,并将名称复制到您的全局变量。
但它确实全部。它不会自动查找旧模块的每个引用,更不用说旧模块中定义的任何内容等,并将它们全部修复以引用替换版本。 (怎么可能呢?在新模块中甚至可能没有 替换版本。就此而言,如果您的值由旧代码计算并且将以不同方式计算,它会有什么重新运行自导入模块以来您完成的所有事情。)
文档(上面链接的)以不同的术语解释它,但让我们具体化,所以我可以更直接地解释它。
创建此文件:
# mod.py
class Spam(object):
def eggs(self):
print('spam spam spam spam')
现在:
$ python
>>> import mod
>>> spam = mod.Spam()
>>> spam.eggs()
spam spam spam spam
现在让我们编辑它:
# 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
当您通过调用spam
创建mod.Spam()
时,会在全局变量中查找'mod'
,然后在生成的模块中查找'Spam'
,然后调用其构造函数和初始化程序,为您提供一个__class__
是对该mod.Spam
类的引用的对象。
当您致电spam.eggs()
时,Python在全局词典中查找'spam'
,在'eggs'
对象的词典中查找spam
,然后失败,在'eggs'
对象的字典中查找spam.__class__
。我们知道,这是mod.Spam
对象,它有一个eggs
方法,因此会被调用。
现在,在我们reload(mod)
之后,有一个名为'mod'
的新对象,它有一个名为'Spam'
的新类作为成员。但旧的mod
和mod.Spam
对象 - 以及您的spam
仍然存在。现有的spam
仍然引用其mod.Spam
中的旧__class__
。所以,当你第二次打电话给spam.eggs()
时,事情就像以前一样。 Python将'spam'
查找为全局,在'eggs'
中首先查找spam
,然后在spam.__class__
中查找与之前相同的类,并调用与之前相同的函数。
当我们再次调用morespam
来构建mod.Spam()
时,现在在全局变量中查找'mod'
并找到新的'mod'
。然后它在该模块中查找'Spam'
并找到新类。因此,我们有一个__class__
是新mod.Spam
的实例。当我们调用它的eggs
方法时,同样的事情发生在上面,但现在它被调用的新函数。
使用from mod import *
代替import mod
会让事情变得难以理解,但基本思路是一样的。 from mod import *
不会将mod
放入您的全局变量中,而是复制所有非私有全局变量(mod.__all__
中列出的任何内容,或者,如果不存在任何此类事物,则为在mod
中,不以单个下划线开头)到您的全局变量。因此,reload
创建一个新的模块对象,第二个from mod import *
将所有新模块的非私有全局变量复制到您的全局变量中,替换旧的变量。但是,您的spam
实例仍然是旧Spam
的实例,而不是新实例。
答案 1 :(得分:1)
我想到了三种可能性(一种是@ abarnert&#39; s):
pyspark.hbase
有__all__
,您尝试使用的课程不在其中pyspark.hbase
没有__all__
,但您的班级名称/职能/等等以_
开头。 __all__
用作模块定义其官方API的方式。它还用于提供在发出from ... import *
时要导入的名称列表。如果未定义__all__
,则在该模块上使用_
时,将加载模块中不以from ... import *
开头的任何名称。
无论是否定义__all__
,您都可以通过直接请求明确加载模块中定义的任何名称:
from xyz import _private
会将_private
加载到您模块的命名空间中。