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

时间:2009-11-16 03:41:29

标签: python python-import

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

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

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

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

修改

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

9 个答案:

答案 0 :(得分:77)

答案

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

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

# python3.x would require
# from importlib import reload
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

答案 1 :(得分:47)

如果Y是一个模块(并且X是一个包)reload(Y)会没问题 - 否则,你会看到为什么好的Python风格指南(比如我的雇主)对从不导入任何除了一个模块(这是众多重要原因中的一个 - 然而人们仍然会直接导入函数和类,无论我多么解释它一个好主意; - )。

答案 2 :(得分: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

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

答案 3 :(得分:7)

from modulename import func

import sys
reload(sys.modules['modulename'])
from modulename import func

答案 4 :(得分:4)

如果你想这样做:

GROUP BY

请改为:

SELECT sum(mean(value) GROUP BY "instance") FROM "queues_value" WHERE "host" =~ /$host/ AND "type" = 'rabbitmq_messages' AND $timeFilter GROUP BY time($interval), "host"

现在你可以按照你计划的方式使用myobject(没有令人厌烦的不可读的mymodule引用)。

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

SELECT sum(value) FROM (SELECT mean(value) FROM "queues_value" WHERE "host" =~ /$host/ AND "type" = 'rabbitmq_messages' AND $timeFilter GROUP BY time($interval), "host", "instance") GROUP BY time($interval), "host"

答案 5 :(得分:2)

假设您使用了from X import Y,您有两种选择:

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

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

一些注意事项:

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

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

答案 6 :(得分:1)

  1. reload()模块X
  2. reload()模块从Y导入X
  3. 请注意,重新加载不会更改已绑定在其他命名空间中的已创建对象(即使您遵循Alex的样式指南)。

答案 7 :(得分:0)

为了跟进AlexMartelli'sCatskul's的答案,有一些非常简单但令人讨厌的案例似乎让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类与自身不同步,这很奇怪。

答案 8 :(得分:0)

如果您在Jupyter环境中工作,并且已经拥有from module import function可以使用魔术功能autoreload

%load_ext autoreload
%autoreload
from module import function

here中给出了IPython中autoreload的介绍。