115

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

我想知道当我使用from X import Y.

该语句reload Y不起作用,因为 Y 本身不是模块,而只是模块内部的一个组件(在这种情况下是一个类)。

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

编辑:

为了澄清起见,问题是关于从模块 X导入类或函数 Y并在更改时重新加载,而不是从包 X 中导入模块 Y。

4

9 回答 9

122

回答

从我的测试来看,标记的答案(暗示简单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"

蟒蛇:

>>> 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
于 2012-07-30T15:04:18.340 回答
54

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

于 2009-11-16T03:44:48.037 回答
17
from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func
于 2014-02-27T16:00:57.233 回答
6

首先,如果可以避免的话,你根本不应该使用 reload。但是让我们假设你有你的理由(即在 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

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

于 2009-11-16T06:21:51.513 回答
4

如果你想这样做:

from mymodule import myobject

改为这样做:

import mymodule
myobject=mymodule.myobject

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

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

reload(mymodule)
myobject=mymodule.myobject
于 2016-08-17T13:41:52.147 回答
3

如果您在 jupyter 环境中工作,并且您已经from module import function可以使用魔法功能,autoreload通过

%load_ext autoreload
%autoreload
from module import function

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

于 2019-06-24T03:08:04.867 回答
2

假设你使用过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 和重新加载您的模块,即使重新加载所有模块(例如: using [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ])也可能在重新加载 Z 之前重新加载 X - 并且比不刷新 Y 的值。

于 2017-08-18T22:32:20.670 回答
1
  1. reload()模块X
  2. reload()模块YX.

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

于 2009-11-16T05:58:28.213 回答
0

只是为了跟进AlexMartelliCatskul 的reload答案,至少在 Python 2 中,有一些非常简单但令人讨厌的案例似乎令人困惑。

假设我有以下源代码树:

- foo
  - __init__.py
  - bar.py

内容如下:

初始化.py:

from bar import Bar, Quux

酒吧.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班级与自身不同步,这很奇怪。

于 2017-10-17T23:06:39.403 回答