如何在Python Interpreter中重新导入更新的包?

How to re import an updated package while in Python Interpreter?

本问题已经有最佳答案,请猛点这里访问。

我经常在Python解释器中测试我的模块,当我看到错误时,我会快速更新.py文件。但我该如何让它反映在口译员身上呢?到目前为止,我一直在退出并重新输入解释器,因为重新导入文件对我来说不起作用。


python3的更新:(引自已回答的答案,因为此处的最后一个编辑/注释建议使用不推荐的方法)

In Python 3, reload was moved to the imp module. In 3.4, imp was deprecated in favor of importlib, and reload was added to the latter. When targeting 3 or later, either reference the appropriate module when calling reload or import it.

外卖:

  • python3>=3.4:importlib.reload(packagename)
  • python3<3.4:imp.reload(packagename)
  • python2:继续下面

使用reload内置功能:

https://docs.python.org/2/library/functions.html重新加载

When reload(module) is executed:

  • Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called a second time.
  • As with all other objects in Python the old objects are only reclaimed after their reference counts drop to zero.
  • The names in the module namespace are updated to point to any new or changed objects.
  • Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 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


以上关于reload()imp.reload()的回答都是不赞成的。

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

最好用importlib.reload()代替。


So, far I have been exiting and reentering the Interpreter because re importing the file again is not working for me.

是的,只是说import再次提供了来自sys.modules的模块的现有副本。

您可以说reload(module)更新sys.modules并获取该单个模块的新副本,但是如果任何其他模块引用了原始模块或原始模块中的任何对象,它们将保留旧的引用,并且会发生非常混乱的事情。

因此,如果您有一个模块a,它取决于模块bb的更改,那么您必须先"重新加载B",然后再"重新加载A"。如果您有两个相互依赖的模块,当这些模块是同一个包的一部分时,这是非常常见的,您不能同时重新加载它们:如果您重新加载p.a,它将获得对旧p.b的引用,反之亦然。唯一的方法是在再次进口之前,从sys.modules中删除它们的项目,同时卸载它们。这是棘手的,并有一些实际的陷阱,与作为失败的相对导入标记的非模块条目有关。

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

总而言之:除了一个独立脚本加载一个独立模块的最简单情况外,reload()非常难纠正;如果您使用的是"包",那么您最好继续循环解释器。


在Python3中,行为会改变。

1
>>> import my_stuff

…对我的东西做点什么,然后再做:

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

你得到一个全新的,重新加载我的东西。


无论您导入一个模块多少次,您都将从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等钥匙不建议使用模块。
  • 在许多情况下,扩展模块不是设计为多次初始化,并可能在任意情况下失败重新加载时的方式。如果一个模块从另一个模块导入对象使用fromimport…,另一个模块调用reload()。不重新定义从中导入的对象-一种方法是重新执行from语句,另一个是使用import语句,并合格改为名称(module.name)。
  • 如果模块实例化类,重新加载定义类的模块不会影响实例的方法定义-它们继续使用旧的类定义。派生类也是如此。

外部包:

重新导入-重新导入当前支持python 2.4到2.7。

xreload-这是通过在临时命名空间中执行模块来实现的,然后就地修补类、方法和函数。这样可以避免需要修补实例。将新对象复制到目标中命名空间。

LiveCoding——代码重新加载允许正在运行的应用程序根据所使用的Python脚本的变化来更改其行为。当库检测到python脚本已被修改时,它会重新加载该脚本,并将以前提供的对象替换为新重新加载的版本。作为一种工具,它允许程序员避免工作流程中断和相应的焦点丢失。它使它们能够保持流动状态。如果以前他们可能需要重新启动应用程序才能使更改后的代码生效,那么可以立即应用这些更改。


简短回答:

尝试使用reimport:python的完整功能重新加载。

更长的回答:

看起来这个问题是在重新导入发布之前被问到/回答的,重新导入本身就是一个"针对python的全功能重新加载":

This module intends to be a full featured replacement for Python's reload function. It is targeted towards making a reload that works for Python plugins and extensions used by longer running applications.

Reimport currently supports Python 2.4 through 2.6.

By its very nature, this is not a completely solvable problem. The goal of this module is to make the most common sorts of updates work well. It also allows individual modules and package to assist in the process. A more detailed description of what happens is on the overview page.

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


基本上像所有代码的电源一样重新加载。但它不会改变已经实例化的对象或引用函数的代码。从他的回答延伸到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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


不确定这是否能满足所有期望,但您可以这样做:

1
2
>>> del mymodule
>>> import mymodule

有关如何不重新加载依赖模块以及可能产生的效果的详细说明,请参见此处:

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

PyUnit解决这一问题的方法是通过覆盖"导入"来跟踪依赖模块,然后从sys.modules中删除每个模块并重新导入。不过,他们可能只是重新装上了。


1
2
import sys
del sys.modules['module_name']


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

1
2
import sys
del sys.modules['module_name']

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

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