Python:重新加载组件Y与'从X导入Y'导入?

在Python中,一旦我使用import X X在解释器会话中import X了模块import X ,并且模块在外部发生了更改,则可以使用reload(X)重新加载模块。 这些更改将在我的口译员会话中提供。

我想知道如果这也可以使用from X import Y从模块X导入组件Y.

语句reload Y不起作用,因为Y不是一个模块本身,而只是一个模块内部的一个组件(在本例中是一个类)。

是否有可能在不离开解释器会话(或导入整个模块)的情况下重新加载模块的单个组件?

编辑:

为了澄清,问题是关于从模块X导入一个类或函数Y ,并重新加载一个变化,而不是来自包X的模块Y.

如果Y是一个模块(而X是一个包),那么reload(Y)就可以了 – 否则,你会明白为什么好的Python风格指南(比如我的雇主的)会说除了模块之外 不要再导入任何东西有很多重要的原因 – 但是人们仍然不断地直接导入函数和类,不pipe我多么解释这不是一个好主意;-)。

回答

从我的testing。 标记的答案,这表明一个简单的reload(X) ,不起作用。

从我可以告诉正确答案是:

 import X reload( X ) from X import Y 

testing

我的testing是以下(Python 2.6.5 + bpython 0.9.5.2)

X.py:

 def Y(): print "Test 1" 

bpython:

 >>> from X import Y >>> print Y() Test 1 >>> # Edit X.py to say "Test 2" >>> print Y() Test 1 >>> reload( X ) # doesn't work because X not imported yet Traceback (most recent call last): File "<input>", line 1, in <module> NameError: name 'X' is not defined >>> import X >>> print Y() Test 1 >>> print XY() Test 1 >>> reload( X ) # No effect on previous "from" statements >>> print Y() Test 1 >>> print XY() # first one that indicates refresh Test 2 >>> from X import Y >>> print Y() Test 2 >>> # Finally get what we were after 

首先,如果你能避免,你不应该使用重装。 但是让我们假设你有你的理由(即在IDLE中debugging)。

重新加载库不会将名称返回到模块的名称空间。 要做到这一点,只需重新分配variables:

 f = open('zoo.py', 'w') f.write("snakes = ['viper','anaconda']\n") f.close() from zoo import snakes print snakes f = open('zoo.py', 'w') f.write("snakes = ['black-adder','boa constrictor']\n") f.close() import zoo reload(zoo) snakes = zoo.snakes # the variable 'snakes' is now reloaded print snakes 

你可以用其他方法做这个。 您可以通过search本地命名空间来自动执行此过程,并重新分配来自所讨论模块的任何内容,但是我认为我们已经够用了。

 from modulename import func import sys reload(sys.modules['modulename']) from modulename import func 
  1. reload()模块X
  2. reload()模块从X导入Y

请注意,重新加载不会更改已经创build的其他名称空间中绑定的对象(即使您遵循Alex的样式指南)。

如果你想这样做:

 from mymodule import myobject 

做这个,而不是:

 import mymodule myobject=mymodule.myobject 

您现在可以按照您计划的方式使用myobject(无处不在的无法读取的mymodule引用)。

如果您正在以交互方式工作,并且想从mymodule重新加载myobject,那么现在可以使用:

 reload(mymodule) myobject=mymodule.myobject 

假设你使用from X import Y ,你有两个select:

 reload(sys.modules['X']) reload(sys.modules[__name__]) # or explicitly name your module 

要么

 Y=reload(sys.modules['X']).Y 

很less考虑:

答:如果导入作用域不是模块范围的(例如:在函数中导入),则必须使用第二个版本。

B.如果将Y从另一个模块(Z)导入到X中,则必须重新加载Z,而不是重新加载X并重新加载模块,甚至重新加载所有模块(例如, [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]使用[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]可能会在重载Z之前重载X,而不是刷新Y的值, [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]

只是为了跟上AlexMartelli和Catskul的答案,至less在Python 2中,有一些非常简单但是令人讨厌的情况,似乎混淆了reload

假设我有以下源代码树:

 - foo - __init__.py - bar.py 

具有以下内容:

init.py:

 from bar import Bar, Quux 

bar.py:

 print "Loading bar" class Bar(object): @property def x(self): return 42 class Quux(Bar): object_count = 0 def __init__(self): self.count = self.object_count self.__class__.object_count += 1 @property def x(self): return super(Quux,self).x + 1 def __repr__(self): return 'Quux[%d, x=%d]' % (self.count, self.x) 

这工作得很好,没有使用reload

 >>> from foo import Quux Loading bar >>> Quux() Quux[0, x=43] >>> Quux() Quux[1, x=43] >>> Quux() Quux[2, x=43] 

但是尝试重新加载,它或者没有效果或者腐败的东西:

 >>> import foo Loading bar >>> from foo import Quux >>> Quux() Quux[0, x=43] >>> Quux() Quux[1, x=43] >>> reload(foo) <module 'foo' from 'foo\__init__.pyc'> >>> Quux() Quux[2, x=43] >>> from foo import Quux >>> Quux() Quux[3, x=43] >>> reload(foo.bar) Loading bar <module 'foo.bar' from 'foo\bar.pyc'> >>> Quux() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "foo\bar.py", line 17, in __repr__ return 'Quux[%d, x=%d]' % (self.count, self.x) File "foo\bar.py", line 15, in x return super(Quux,self).x + 1 TypeError: super(type, obj): obj must be an instance or subtype of type >>> Quux().count 5 >>> Quux().count 6 >>> Quux = foo.bar.Quux >>> Quux() Quux[0, x=43] >>> foo.Quux() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "foo\bar.py", line 17, in __repr__ return 'Quux[%d, x=%d]' % (self.count, self.x) File "foo\bar.py", line 15, in x return super(Quux,self).x + 1 TypeError: super(type, obj): obj must be an instance or subtype of type >>> foo.Quux().count 8 

我可以确保bar子模块重新加载的唯一方法是重新reload(foo.bar) ; 我访问重新加载的Quux类的唯一方法是到达并从重新加载的子模块抓取它; 但是foo模块本身保持原来的Quux类对象,大概是因为它使用from bar import Bar, Quux (而不是import bar跟着Quux = bar.Quux ); 而且这个Quux类与自己不同步,这只是奇怪的。