在Python中,一旦我在解释器会话中使用导入了模块X import X
,并且模块在外部进行了更改,就可以使用来重新加载该模块reload(X)
。然后,这些更改将在我的解释器会话中可用。
我想知道当我使用从模块X导入组件Y时是否也可行from X import Y
?
该语句reload Y
不起作用,因为Y本身不是模块,而是模块内部的仅组件(在这种情况下为类)。
是否有可能在不离开解释器会话(或导入整个模块)的情况下重新加载模块的各个组件?
编辑:
为了澄清起见,问题在于从模块X导入类或函数Y并在更改时重新加载,而不是从包X重新加载模块Y。
如果Y是一个模块(而X是一个包)reload(Y)
就可以了-否则,您将明白为什么优秀的Python样式指南(例如,我的老板的)会说除了模块之外,不要导入任何东西(这是许多重要原因之一) -但是人们仍然继续直接导入函数和类,无论我解释多少,这都不是个好主意;-)。
回答
根据我的测试,标记为简单的答案reload(X)
是行不通的。
从我可以看出的正确答案是:
from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y
测试
我的测试如下(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 X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2
>>> # Finally get what we were after
from modulename import func
import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func
首先,如果可以避免,则根本不应该使用重装。但是,让我们假设您有自己的理由(即在IDLE中进行调试)。
重新加载库不会使名称重新回到模块的命名空间中。为此,只需重新分配变量:
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
您可以通过其他几种方式执行此操作。您可以通过搜索本地名称空间,然后重新分配所讨论模块中的任何内容来自动化该过程,但是我认为我们已经足够邪恶了。
如果要这样做:
from mymodule import myobject
改为这样做:
import mymodule
myobject=mymodule.myobject
现在,您可以以与计划相同的方式使用myobject(无需到处都是烦人的,难以理解的mymodule引用)。
如果您正在交互工作,并且想要从mymodule重新加载myobject,现在可以使用:
reload(mymodule)
myobject=mymodule.myobject
假设您使用from X import Y
,则有两个选择:
reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module
要么
Y=reload(sys.modules['X']).Y
一些注意事项:
A.如果导入范围不在模块范围内(例如,在函数中导入)-您必须使用第二个版本。
B.如果Y是从另一个模块(Z)导入到X中的,则-您必须重新加载Z,而不是重新加载X,然后重新加载模块,即使重新加载所有模块(例如使用[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]
)也可能在重新加载Z之前重新加载X-并且不刷新Y的值。
reload()
模块X
,reload()
Y
从中导入模块X
。
请注意,重新加载不会更改绑定在其他命名空间中的已创建对象(即使您遵循Alex的样式指南)。
如果你在一个jupyter环境中工作,并且已经有from module import function
可以使用神奇的功能,autoreload
由
%load_ext autoreload
%autoreload
from module import function
引进的autoreload
在IPython中给出了这里。
只是为了跟进AlexMartelli和Catskul的回答,reload
至少在Python 2中,有些真正简单但令人讨厌的案例似乎令人困惑。
假设我有以下源代码树:
- 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
堂课与自己不同步,这很奇怪。
文章标签:python , python-import
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!
评论已关闭!