如何卸载(重新加载)Python模块?

如何卸载(重新加载)Python模块?

我有一个长期运行的Python服务器,希望能够在不重新启动服务器的情况下升级服务。最好的办法是什么?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()


森栏
浏览 1942回答 4
4回答

缥缈止盈

当模块已经导入时,可以使用reload内置功能:from&nbsp;importlib&nbsp;import&nbsp;reload&nbsp;&nbsp;#&nbsp;Python&nbsp;3.4+&nbsp;only.import&nbsp;foowhile&nbsp;True: &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Do&nbsp;some&nbsp;things. &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;is_changed(foo): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo&nbsp;=&nbsp;reload(foo)在Python 3中,reload被移到imp模块。在3.4,imp被反对赞成importlib,和reload加入了后者。当目标为3或更高版本时,在调用reload或者进口。我想这就是你想要的。像Django的开发服务器这样的Web服务器使用它,这样您就可以看到代码更改的效果,而无需重新启动服务器进程本身。引用文档:重新编译Python模块的代码,重新执行模块级的代码,定义一组新的对象,这些对象绑定到模块字典中的名称。扩展模块的init函数不是第二次调用。与Python中的所有其他对象一样,只有在引用计数降到零之后,旧对象才会被回收。更新模块命名空间中的名称以指向任何新的或更改的对象。其他对旧对象的引用(例如模块外部的名称)不会反弹以引用新对象,如果需要的话,必须在它们出现的每个名称空间中进行更新。正如你在问题中指出的,你必须重建Foo对象的Foo类驻留在foo模块。

繁星淼淼

在Python3.0-3.3中,您将使用:imp.reload(module)这个BDFL有回答这个问题。然而,imp在3.4中被否决,赞成importlib(谢谢@斯特凡!).I&nbsp;想因此,您现在可以使用importlib.reload(module)虽然我不确定。

胡说叔叔

如果一个模块不是纯Python,那么删除它就会特别困难。以下是以下内容:如何真正删除导入的模块?您可以使用sys.getrefcount()查找引用的实际数量。>>>&nbsp;import&nbsp;sys,&nbsp;empty,&nbsp;os>>>&nbsp;sys.getrefcount(sys)9>>>&nbsp;sys.getrefcount(os)6>>>&nbsp;sys.getrefcount(empty)3大于3的数字表示很难摆脱模块。自带的“空”模块(不包含任何内容)应该在之后被垃圾收集。>>>&nbsp;del&nbsp;sys.modules["empty"]>>>&nbsp;del&nbsp;empty第三个引用是getrefcount()函数的工件。

ibeautiful

reload(module)但前提是它是完全独立的。如果任何其他东西都有对模块(或属于模块的任何对象)的引用,那么您将得到一些微妙而又奇怪的错误,这些错误是由旧代码在您预期的时间内停留较长时间造成的,并且类似的情况如下isinstance不跨相同代码的不同版本工作。如果您有单向依赖项,则还必须重新加载所有依赖于重新加载模块的模块,以消除对旧代码的所有引用。然后递归地重新加载依赖于重新加载模块的模块。如果您有循环依赖项(例如在处理重新加载包时非常常见),则必须一次卸载组中的所有模块。你不能用reload()因为它将在更新依赖项之前重新导入每个模块,从而允许旧的引用进入新模块。在这种情况下,做这件事的唯一方法就是黑。sys.modules有点不受支持。你得逐个删除sys.modules条目,希望在下一次导入时重新加载,并删除值为None若要处理与缓存失败的相对导入有关的实现问题,请执行以下操作。这不是很好,但只要您有一组完全独立的依赖项,并且不将引用放在其代码基之外,这是可行的。最好重新启动服务器。*-)
打开App,查看更多内容
随时随地看视频慕课网APP