在Python中重新导入单个函数

6 投票
4 回答
4933 浏览
提问于 2025-04-16 08:13

在使用Python的交互模式时,你可以先导入一个模块。如果这个模块有了改动,比如修复了一个bug,你可以简单地使用reload()命令来重新加载这个模块。

但是,如果我不是导入整个模块,而是用'from M import f, g'这种方式导入的,那有没有办法只重新导入g呢?

我试过通过'del g'来删除这个函数,然后还把目录里的.pyc文件删掉,但都没用。当我再次用'from M import g'导入时,还是加载了旧的g。

4 个回答

2

因为这只是为了交互式解释器,我觉得像下面这样的做法:

def my_reload(mod, name):
    reload(mod)
    globals()[name] = getattr(mod, name)

myreload(somemodule, "some_function")

也不是太糟糕。这只是像平常一样重新加载模块,然后把指向旧对象的名字重新绑定到新对象上。这样做在所有可以用reload的情况下都应该有效。或者,你可以编写代码来获取实际对象,并通过它的__name__属性来获取名字。函数、类和模块都有__name__属性,但像模块级别的字典就没有,所以灵活性就差一些。

这种做法不会替换其他地方对对象的引用,除了全局的引用,但即使你最开始是用点号命名访问的,reload也不会替换那些引用。一旦对一个对象的引用变得松散,你就没什么办法了。

5

对于 from M import f, g 这种写法,如果 M 不是一个官方的 Python 模块,可以使用:

import sys
import importlib
importlib.reload(sys.modules['M'])

然后,重新导入 fg,可以使用:

from M import f,g

如果 M 是一个官方的 Python 模块,那就使用:

import importlib
importlib.reload(M)
from M import f,g
9

当你使用 from foo import bar 这行代码时,其实是把整个模块都引入了。你只是把符号 bar 的一个副本放到了当前的命名空间里。换句话说,你并不是单独引入这个函数。

另外,reload 这个功能并不是完全可靠的(比如它对编译过的C模块就不管用)。我建议你退出并重新启动你的解释器。

撰写回答