如何在 Python 解释器中重新导入更新的包?[重复]
- 2025-04-15 09:19:00
- admin 原创
- 34
问题描述:
我经常在 Python 解释器中测试模块,一旦发现错误,就会快速更新 .py 文件。但是,如何让错误反映到解释器中呢?到目前为止,我一直都是退出解释器再重新进入,因为重新导入文件对我来说不起作用。
解决方案 1:
Python3 的更新:(引用自已经回答的答案,因为这里的最后一次编辑/评论建议使用一种不推荐使用的方法)
在 Python 3 中,
reload
被移至imp
模块。在 3.4 中,已被弃用,imp
取而代之的是,并被添加到后者。当面向 3 或更高版本时,请在调用时引用相应的模块或导入它。importlib
`reload`reload
要点:
Python3 >=3.4:
importlib.reload(packagename)
Python3 <3.4:
imp.reload(packagename)
Python2:继续下面
使用reload
内置函数:
https://docs.python.org/2/library/functions.html#reload
何时
reload(module)
执行:
Python 模块的代码会被重新编译,模块级代码也会重新执行,从而定义一组新的对象,这些对象会绑定到模块字典中的名称。扩展模块的 init 函数不会被再次调用。
与 Python 中的所有其他对象一样,旧对象只有在其引用计数降至零后才会被回收。
模块命名空间中的名称已更新以指向任何新的或更改的对象。
对旧对象的其他引用(例如模块外部的名称)不会被重新绑定以引用新对象,并且如果需要,必须在它们出现的每个命名空间中进行更新。
例子:
# Make a simple function that prints "version 1"
shell1$ echo 'def x(): print "version 1"' > mymodule.py
# Run the module
shell2$ python
>>> import mymodule
>>> mymodule.x()
version 1
# Change mymodule to print "version 2" (without exiting the python REPL)
shell2$ echo 'def x(): print "version 2"' > mymodule.py
# Back in that same python session
>>> reload(mymodule)
<module 'mymodule' from 'mymodule.pyc'>
>>> mymodule.x()
version 2
解决方案 2:
reload()
以上有关或的所有答案imp.reload()
均已弃用。
reload()
不再是 python 3 中的内置函数,并且imp.reload()
被标记为已弃用(参见help(imp)
)。
最好还是用它importlib.reload()
代替。
解决方案 3:
到目前为止,我已经退出并重新进入解释器,因为重新导入文件对我来说不起作用。
是的,只需import
再说一遍就可以为您提供模块的现有副本sys.modules
。
您可以说reload(module)
更新sys.modules
并获取该单个模块的新副本,但如果任何其他模块引用了原始模块或原始模块中的任何对象,它们将保留其旧引用,并且会发生非常令人困惑的事情。
因此,如果您有一个a
依赖于模块的模块b
,并且b
它发生了变化,那么您必须“重新加载 b”,然后“重新加载 a”。如果您有两个相互依赖的模块(当这些模块属于同一个包时这种情况非常常见),那么您不能同时重新加载它们:如果您重新加载,p.a
它将获得对旧模块的引用p.b
,反之亦然。唯一的方法是通过从中删除它们的项目来同时卸载它们sys.modules
,然后再导入它们。这很麻烦,并且在模块条目为 None 作为失败相对导入标记时存在一些实际陷阱。
如果你有一个模块将其对象的引用传递给系统模块 - 例如它注册了一个编解码器,或者添加了一个警告处理程序 - 你就陷入困境了;如果不混淆 Python 环境的其余部分,你就无法重新加载系统模块。
总而言之:除了最简单的情况(即一个独立脚本加载一个独立模块)之外,其他所有情况reload()
都很难做到正确;如果如您所暗示的那样,您正在使用“包”,那么继续循环解释器可能会更好。
解决方案 4:
在 Python 3 中,行为发生了变化。
>>> import my_stuff
...用 my_stuff 做一些事情,然后:
>>>> import imp
>>>> imp.reload(my_stuff)
您将获得一个全新的、重新加载的 my_stuff。
解决方案 5:
无论导入模块多少次,您都会获得相同的模块副本sys.modules
- 该副本最初是加载的import mymodule
我回答得晚了,因为上面/之前的每个答案都有一点答案,所以我试图用一个答案来总结所有内容。
使用内置函数:
对于Python 2.x - 使用内置reload(mymodule)
函数。
对于Python 3.x - 使用imp.reload(mymodule)
。
对于Python 3.4 - 在 Python 3.4 中imp
已被弃用,转而使用importlib
ieimportlib.reload(mymodule)
几点注意事项:
重新加载内置模块或动态加载模块通常没什么用。不建议重新加载
sys
、__main__
和其他关键模块。builtins
很多情况下,扩展模块并非设计为可多次初始化,并且在重新加载时可能会以任意方式失败。如果一个模块使用
from
……从另一个模块导入对象import
,则调用reload()
另一个模块并不会重新定义从其导入的对象——解决这个问题的一种方法是重新执行该from
语句,另一种方法是使用import
限定名(module.name)。如果模块实例化了某个类的实例,则重新加载定义该类的模块不会影响实例的方法定义——它们将继续使用旧的类定义。派生类也是如此。
外部包:
reimport - Reimport 目前支持 Python 2.4 到 2.7。
xreload - 通过在临时命名空间中执行模块,然后就地修补类、方法和函数来实现。这样就无需修补实例。新的对象将被复制到目标命名空间中。
livecoding - 代码重载允许正在运行的应用程序根据其使用的 Python 脚本的更改来改变其行为。当该库检测到 Python 脚本已被修改时,它会重新加载该脚本,并用新加载的版本替换之前可用的对象。作为一种工具,它可以帮助程序员避免工作流程中断以及随之而来的注意力分散。它使他们能够保持流畅的状态。以前,他们可能需要重新启动应用程序才能使更改的代码生效,而现在这些更改可以立即应用。
解决方案 6:
简短回答:
尝试使用reimport:Python 的全功能重新加载。
更长的答案:
看起来这个问题是在reimport发布之前提出/回答的,reimport 自称是“Python 的全功能重新加载”:
此模块旨在成为 Python reload 函数的全功能替代品。其目标是为长期运行的应用程序所使用的 Python 插件和扩展提供 reload 功能。
Reimport 目前支持 Python 2.4 到 2.6。
就其本质而言,这不是一个完全可以解决的问题。此模块的目标是使最常见的更新类型能够正常工作。它还允许各个模块和软件包协助完成此过程。有关更详细的描述,请参阅概述页面。
注意:尽管reimport
明确支持 Python 2.4 到 2.6,但我一直在 2.7 上尝试过,而且它似乎运行良好。
解决方案 7:
基本上像 allyourcode 的答案那样重新加载。但它不会改变已实例化对象或引用函数的底层代码。扩展他的答案:
#Make a simple function that prints "version 1"
shell1$ echo 'def x(): print "version 1"' > mymodule.py
# Run the module
shell2$ python
>>> import mymodule
>>> mymodule.x()
version 1
>>> x = mymodule.x
>>> x()
version 1
>>> x is mymodule.x
True
# Change mymodule to print "version 2" (without exiting the python REPL)
shell2$ echo 'def x(): print "version 2"' > mymodule.py
# Back in that same python session
>>> reload(mymodule)
<module 'mymodule' from 'mymodule.pyc'>
>>> mymodule.x()
version 2
>>> x()
version 1
>>> x is mymodule.x
False
解决方案 8:
不确定这是否可以完成所有预期的事情,但你可以这样做:
>>> del mymodule
>>> import mymodule
解决方案 9:
import sys
del sys.modules['module_name']
解决方案 10:
请参阅此处,了解有关如何不重新加载依赖模块以及可能产生的影响的详细说明:
http://pyunit.sourceforge.net/notes/reloading.html
pyunit 解决这个问题的方法是,通过重写 import 来跟踪依赖模块,然后从 sys.modules 中删除每个依赖模块,再重新导入。不过,他们或许可以直接重新加载它们。
解决方案 11:
dragonfly 的答案对我有用(python 3.4.3)。
import sys
del sys.modules['module_name']
这是一个较低级别的解决方案:
exec(open("MyClass.py").read(), globals())
扫码咨询,免费领取项目管理大礼包!