Python:使用'from X import Y'重新加载组件Y?

csc*_*hol 80 python python-import

在Python中,一旦我在解释器会话中导入模块X import X,并且模块在外部更改,我可以重新加载模块reload(X).然后,在我的翻译会话中可以使用这些更改.

我想知道当我从模块X导入组件Y时是否也可以这样做from X import Y.

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

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

编辑:

为了澄清,问题是从模块X导入类或函数Y并重新加载更改,而不是从包X中重新模块Y.

Cat*_*kul 86

回答

从我的测试.标记的答案,表明一个简单的reload(X),不起作用.

据我所知,正确的答案是:

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y
Run Code Online (Sandbox Code Playgroud)

测试

我的测试如下(Python 2.6.5 + bpython 0.9.5.2)

X.py:

def Y():
    print "Test 1"
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 哇。我发现这真的很方便。谢谢!我现在用它作为一个衬垫:import X; 重新加载( X ); 从 X 进口 Y (2认同)
  • 这是一个比公认的更好的答案。警告人们是公平的,但每个人的用例都不同。在某些情况下,重新加载类确实很有帮助,例如,当您使用 python 控制台并希望在不丢失会话的情况下加载对代码的更改时。 (2认同)
  • 这似乎并不总是有效。我有一个模块“Foo”,它有一个“__init__.py”,可以获取子模块...我将发布一个答案作为反例。 (2认同)

Ale*_*lli 47

如果Y是一个模块(而X是一个包)就没问题了reload(Y) - 否则,你就会明白为什么好的Python风格指南(比如我的雇主)说永远不会导入任何东西,除了模块(这是很多很好的理由之一) - 然而人们仍然直接导入函数和类,无论我多么解释它不是一个好主意;-).

  • @cschol:Python的禅,最后一节(从交互式提示中导入这个`以查看Python的Zen); 所有原因_why_名称空间都是一个好主意(直接的本地视觉线索,名称被查找,易于模拟/注入测试,重新加载的能力,模块通过重新定义一些条目灵活变化的能力,可预测和可控制关于序列化和恢复数据的行为[[例如通过酸洗和去除],等等 - SO评论几乎不足以公正地对待这个丰富的,长期的论点!!! - ) (6认同)
  • 请注意,在Python 3中,重新加载不再位于默认命名空间中,而是已移至`importlib`包.`importlib.reload(Y)`https://docs.python.org/3.4/library/importlib.html?highlight=reload#functions另见http://stackoverflow.com/questions/961162/reloading-module-giving -error重载此结果不限定 (3认同)
  • @ThorSummoner,绝对不是 - 它意味着"总是导入MODULES",所以"来自my.package import mymodule"绝对没问题,确实是首选 - 只是,永远不要导入类,函数等 - 总是,只有,永远*模块*. (3认同)
  • 投反对票。为什么?这不是正确的答案。Catskul 于 2012 年 7 月 30 日 15:04 给出了正确答案。 (3认同)
  • 我明白你的意思。您是否愿意详细说明为什么它不是一个好主意的任何其他充分理由? (2认同)

wis*_*sty 7

首先,如果可以避免,你根本不应该使用重新加载.但是我们假设你有自己的理由(即在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
Run Code Online (Sandbox Code Playgroud)

你可以通过其他几种方式做到这一点.您可以通过搜索本地命名空间来自动化该过程,并重新分配来自相关模块的任何内容,但我认为我们已经足够邪恶了.


mir*_*rek 7

from modulename import func

import sys
reload(sys.modules['modulename'])
from modulename import func
Run Code Online (Sandbox Code Playgroud)

  • 这是原始问题的唯一有效解决方案,但得票太少! (2认同)

Yan*_*ang 5

如果您在 jupyter 环境中工作,并且您已经from module import function可以使用 magic 函数,autoreload通过

%load_ext autoreload
%autoreload
from module import function
Run Code Online (Sandbox Code Playgroud)

这里autoreload给出了IPython中的介绍。