如何在Python中“重新导入”模块,以便在导入后更改代码。

134

我有一个foo.py文件

def foo():
    print "test"

在IPython中我使用:

In [6]:  import foo
In [7]:  foo.foo()
test

然后我将 foo() 改为:

def foo():
    print "test changed"

在IPython中,调用后的结果仍为test

In [10]:  import foo
In [11]:  foo.foo()
test

然后我使用:

In [15]: del foo
In [16]:  import foo
In [17]:  foo.foo()
test

我在与 foo.py 同文件夹下删除了 foo.pyc,但运行时仍未更新。

请问如何在运行时重新导入更新后的代码?


5个回答

171

对于Python 2.x

reload(foo)

对于Python 3.x

import importlib
import foo #import the module here, so that it can be reloaded.
importlib.reload(foo)

23
实际上,只需使用“reload(foo)”即可——无需重新赋值。 - jsbueno
2
我无法让它工作。我得到了TypeError:reload()参数必须是模块。 - Burak
2
@Burak,你传递给reload的参数是一个模块吗?例如:在此之前,你应该先进行import foo - John La Rooy
35
请注意,如果您使用了 from foo import *from foo import bar,则符号 foo 不会被定义。您需要导入 sys 然后执行 reload(sys.modules['foo']) 或者 reload(sys.modules[bar.__module__]) - drevicko
3
请尽快让Python 2.x离开舞台并停止支持它!倒计时退役Python 2.x https://pythonclock.org/. - Martijn van Wezel
显示剩余6条评论

89

IPython3 的自动重载 autoreload 功能非常好用。

这里使用网页上的实际示例。首先加载 'autoreload' 功能。

In []: %load_ext autoreload
In []: %autoreload 2

然后导入您想要测试的模块:

In []: import foo
In []: foo.some_function()
Out[]: 42

在编辑器中打开foo.py文件,将some_function函数的返回值改为43。

In []: foo.some_function()
Out[]: 43

如果您直接导入该函数,它也可以工作。

In []: from foo import some_function
In []: some_function()
Out[]: 42

修改 some_function 函数,使其返回 43。

In []: some_function()
Out[]: 43

2
从foo导入some_function,在Jupyterlab Python 3.7.3下无法工作。 - Robert Nowak
1
最初,似乎在这里也不起作用from foo import some_function。然而,我注意到当我们调用from foo import some_function时,实际的重新加载并没有发生(正如我所期望的那样)。它只有在保存模块文件时才会发生!所以,重新保存foo.py(即使没有任何修改),然后它就会自动重新导入。甚至不需要再次调用import命令。 所以只需保存你的模块文件,然后再试一次,应该会起作用。 - undefined

73

除了gnibbler的回答之外:

在Python 3中发生了改变,变成了:

>>> import imp
>>> imp.reload(foo)

@onnodb指出,自Python 3.4起,imp已被弃用,建议使用importlib

>>> import importlib
>>> importlib.reload(foo)

6
小小的提醒:在Python 3.x的后续版本中,“imp”已被“importlib”取代,但它们的使用方式相同。 - onnodb
1
我真的希望Python3比Python2更好,永远。但是不,他们必须搞砸了一些东西。 - Jürgen A. Erhard

8
如果您希望这一切自动发生,那么可以使用随 iPython 附带的 "autoreload" 模块。请参考此链接

从foo导入some_function,在Jupyterlab Python 3.7.3下无法工作。 - Robert Nowak
1
@Robert Nowak 我遇到了这个问题,但当我仅尝试"import some_function"时,它能够正常工作,而不需要在我的代码中再次使用"from foo"。 - Michael Szczepaniak

2

在 [15] 中,不要使用 del foo,而应该使用

import sys
del sys.modules["foo"]

从模块缓存中删除foo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接