2011-05-31 42 views
4

基本上,我有一个很长的运行过程,我希望能够通过gc卸载模块并恢复内存。我读过关于删除模块How do I unload (reload) a Python module?,它似乎仍然存在悬挂gc引用。如果我将它导入到名称空间中,我可以可靠地取消导入Python模块吗?

但是,如果我只在名称空间内导入和使用模块,该怎么办。换句话说,这样的事情:

ns = {} 
exec somecode in ns 

然后,我会清理命名空间内的sys.modules,并通过删除命名空间本身来完成。

会释放内存在CPython中重用吗?

如果没有,那么是有可能访问使用ctypes的Python的C API的某些部分,做到这一点?

最终结果的重要的部分是,存储器被释放以使得在运行过程中几个星期或几个月,能够可靠地unimport一个模块没有重新加载它。当然,在这段时间内,任何给定的模块都可以被加载和卸载很多次。我假设一个模块可以在加载时创建大量对象,并且正常清理(sys.modules和del)会将这些对象永远留在内存中。

约亨:是的,我可以解决这个在许多方面,但我有兴趣探索的Python的限制。

+2

你肯定你无法通过移动相关的功能整合到一个独立的功能运行与解决此[多](http://docs.python.org/library/multiprocessing.html)或[子] (http://docs.python.org/library/subprocess.html)? – 2011-05-31 01:33:06

+3

听起来像很多工作来节省几个字节。您是否导入了数千个模块,或者为什么您认为卸载它们会值得? – 2011-05-31 01:34:57

回答

3

要取消导入模块,您需要确保已删除对模块的所有引用。这意味着您必须删除导入它的所有模块中的引用,从sys.modules删除引用,删除对该模块中定义的任何函数或类的引用,并删除对模块中定义的类的实例的对象的所有引用。

在几乎所有情况下,这比检索相对较少量的内存是值得的。如果你真的想试试这个,那么gc.get_referrers()可能是有用的,因为你可以删除除了一个已知引用之外的所有模块,然后追溯到找到还有其他引用它的地方。

3

如果你真正想要避免内存泄漏,你最好的办法是安排一次导入模块一次,正常情况下,sys.modules处于通常状态。无论稍后导入模块多少次,它都不会占用更多的内存,因为导入机器只会返回相同的模块。

如果由于某种原因,这仍然不适合,说模块正在动态创建,只需要使用一次,execcertainly isn't the solution。你应该考虑使用另一种执行模式,也许是为了新的流程。

相关问题