如何重新导入一个更新的包,而在Python解释器?

我经常在Python解释器中测试我的模块,当我看到错误时,我会快速更新.py文件。但是我如何让它反映在解释器上呢?所以,到目前为止,我一直在退出并重新进入解释器,因为重新导入文件再次不适合我。

311463 次浏览

为Python3更新:(引用自已回答的答案,因为这里的最后一个编辑/注释建议使用一个已弃用的方法)

在Python 3中,reload被移动到imp模块。在3.4中,imp被弃用,而改用importlib,并将reload添加到后者。当目标为3或更高版本时,在调用reload时引用适当的模块或导入它。

导读:

  • Python3 >= 3.4: importlib.reload(packagename)
  • Python3 & lt;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

所以,到目前为止,我一直在退出并重新进入解释器,因为重新导入文件再次不适合我。

是的,只要再次说import就会给你来自sys.modules的模块的现有副本。

你可以用reload(module)来更新sys.modules并获得该模块的新副本,但如果任何其他模块有对原始模块或来自原始模块的任何对象的引用,它们将保留旧的引用,并且会发生非常混乱的事情。

因此,如果你有一个模块a,它取决于模块b,并且b发生了变化,你必须' reload b '后面跟着' reload a '。如果你有两个相互依赖的模块,当这些模块是同一个包的一部分时,这是非常常见的,你不能同时重载它们:如果你重载p.a,它会得到一个对旧的p.b的引用,反之亦然。唯一的方法是在再次导入它们之前,通过从sys.modules中删除它们的项来同时卸载它们。这很烦人,并且有一些实际的陷阱与模块条目为None作为失败的相对导入标记有关。

如果你有一个模块将其对象的引用传递给系统模块——例如它注册了一个编解码器,或者添加了一个警告处理程序——你就卡住了;你无法在不混淆Python环境的情况下重新加载系统模块。

总之:除了最简单的情况外,对于由一个独立脚本加载一个自包含模块的所有情况,reload()是非常棘手的;如果像你暗示的那样,你正在使用一个“包”,你可能会更好地继续循环解释器。

这里有一个很好的解释,说明你的依赖模块不会被重新加载,以及可能产生的影响:

http://pyunit.sourceforge.net/notes/reloading.html

pyunit解决这个问题的方法是通过覆盖__import__来跟踪依赖模块,然后从sys. exe中删除每个模块。模块并重新导入。不过他们可能只是装弹而已。

基本上是在allyourcode的asnwer中的重新加载。但它不会改变已经实例化的对象或引用函数的底层代码。从他的回答延伸出来:

#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

不确定这是否完成了所有预期的事情,但你可以这样做:

>>> del mymodule
>>> import mymodule

简短的回答:

尝试使用reimport:一个全功能的Python重载

再答:

看起来这个问题是在再输入发布之前被问/回答的,而再输入将自己标榜为“python的全功能重载”:

此模块旨在成为Python重载函数的完整功能替代品。它的目标是使重载适用于运行时间较长的应用程序所使用的Python插件和扩展。

重新导入目前支持Python 2.4到2.6。

就其本质而言,这不是一个完全可以解决的问题。这个模块的目标是使最常见的更新工作良好。它还允许各个模块和包在这个过程中提供帮助。关于所发生的事情的更详细的描述在概述页面上。

注意:虽然reimport显式地支持Python 2.4到2.6,但我一直在2.7上尝试它,它似乎工作得很好。

在Python 3中,行为会发生变化。

>>> import my_stuff

... 用my_stuff做一些事情,然后:

>>>> import imp
>>>> imp.reload(my_stuff)

你会得到一个全新的,重新加载的my_stuff。

上面所有关于reload()imp.reload()的答案都已弃用。

reload()不再是python 3中的内置函数,并且imp.reload()被标记为已弃用(参见help(imp))。

最好使用importlib.reload()代替。

import sys
del sys.modules['module_name']

蜻蜓的回答对我有用(python 3.4.3)。

import sys
del sys.modules['module_name']

下面是一个较低层次的解决方案:

exec(open("MyClass.py").read(), globals())

不管你导入一个模块多少次,你都会从sys.modules得到相同的模块副本——它是在import mymodule第一次加载的

我很晚才回答这个问题,因为上面/之前的每个答案都有一点答案,所以我试图用一个简单的答案来总结。

使用内置函数:

对于Python 2. x -使用内置的reload(mymodule)函数。

对于Python 3. x -使用imp.reload(mymodule)

对于Python 3.4 -在Python 3.4中,imp已被弃用,而支持importlib,即importlib.reload(mymodule)

一些注意事项:

    内置或动态重载通常不是很有用 加载模块。重新加载sys__main__builtins等键 不建议使用“Modules”。李< / >
  • 在很多情况下扩展模块不是 设计用于多次初始化,并可能在任意情况下失败 重新加载时的方式。如果一个模块从另一个模块导入对象 使用fromimport……,为另一个模块调用reload() 不重新定义从它导入的对象-解决这个问题的一个方法是 重新执行from语句,另一个是使用import和qualified 改为命名(module.name)。李< / >
  • 如果一个模块实例化了a的实例 类时,重新加载定义该类的模块不会影响 实例的方法定义-它们继续使用 旧的类定义。对于派生类也是如此

外部包:

再输入 - Reimport目前支持Python 2.4到2.7。

xreload-通过在scratch命名空间中执行模块,然后 适当地修补类、方法和函数。这就避免了 需要修补实例。将新对象复制到目标中 名称空间。< / p >

livecoding -代码重新加载允许运行中的应用程序改变其行为以响应它所使用的Python脚本的变化。当标准库检测到Python脚本已被修改时,它会重新加载该脚本,并用新加载的版本替换之前可用的对象。作为一种工具,它允许程序员避免工作流中断和相应的焦点丢失。它使他们能够保持一种流动的状态。以前他们可能需要重新启动应用程序才能使更改的代码生效,现在可以立即应用这些更改。