如果在名称空间中导入Python模块,是否可以可靠地取消对其的导入?

如果在名称空间中导入Python模块,是否可以可靠地取消对其的导入?,python,Python,基本上,我有一个长时间运行的过程,在这个过程中,我希望能够通过gc取消对模块的影响并恢复内存。我读过关于删除模块的文章,似乎仍然有一些悬而未决的引用阻止了gc 但是,如果我只在名称空间中导入和使用模块,会怎么样。换句话说,类似这样的事情: ns = {} exec somecode in ns 然后我将清理名称空间内的sys.modules,并通过删除名称空间本身来结束 这会释放内存以在CPython中重用吗 如果没有,那么是否可以使用ctypes访问pythoncapi的某些部分来实现这一点

基本上,我有一个长时间运行的过程,在这个过程中,我希望能够通过gc取消对模块的影响并恢复内存。我读过关于删除模块的文章,似乎仍然有一些悬而未决的引用阻止了gc

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

ns = {}
exec somecode in ns
然后我将清理名称空间内的sys.modules,并通过删除名称空间本身来结束

这会释放内存以在CPython中重用吗

如果没有,那么是否可以使用ctypes访问pythoncapi的某些部分来实现这一点

最终结果的重要部分是释放内存,这样一个运行数周或数月的进程就可以可靠地解除对模块的干扰,而无需重新加载模块。当然,在这段时间内,任何给定模块都有可能多次加载和卸载。我假设一个模块在加载时可以创建大量对象,并且通常的清理(sys.modules和del)会将这些对象永远留在内存中


Jochen:是的,我可以用很多方法来解决这个问题,但我对探索Python的局限感兴趣。

如果您真正想要的是避免内存泄漏,那么最好的办法可能是安排以正常方式导入模块一次,使
sys.modules
处于正常状态。不管模块以后被导入多少次,它都不会占用更多的内存,因为导入机器只会不断返回相同的模块


如果出于某种原因,这仍然不合适,比如说模块是动态创建的,只需要使用一次,
exec
。你应该考虑使用一个替代的执行模型,也许是伪造新的进程。

不导入一个模块,你需要确保你已经移除了对模块的所有引用。这意味着您必须从导入它的所有模块中删除引用,从
sys.modules
中删除引用,删除对该模块中定义的任何函数或类的任何引用,以及删除对作为该模块中定义的类实例的对象的所有引用


在几乎所有的情况下,检索相对较少的内存所付出的努力都超过了它的价值。如果你真的想试试这个,那么
gc.get\u referers()
可能很有用,因为您可以删除模块中除一个已知引用以外的所有引用,然后回溯以查找其他引用。

您确定不能通过将相关功能移动到与或一起运行的自包含函数中来解决此问题吗?听起来要节省几个字节需要做很多工作。您是否导入了数千个模块,或者为什么您认为卸载它们是值得的?