exec中动态导入模块后内存未释放,求函数结束后清理模块内存方案
问题
在exec中执行模块导入操作后,函数结束时导入的模块(如pandas)占用的内存未被释放,需要在函数结束后清理该函数内所有通过exec导入的模块,且导入的模块名称不固定。
原代码:
from time import sleep def foo(): code = """import pandas as pd""" exec(code) if __name__ == '__main__': foo() sleep(100)
解决方案
要实现函数结束后清理exec导入的模块,核心是隔离exec的命名空间并跟踪、移除本次导入的模块,具体实现如下:
- 给
exec指定独立的局部命名空间字典,避免导入的模块混入全局命名空间 - 从该命名空间中筛选出模块对象,记录对应的真实模块名(避免别名干扰,比如
pd对应的是pandas) - 从
sys.modules中移除这些模块(仅适用于该模块仅在当前函数内使用的场景,若其他代码依赖该模块,此操作会影响后续使用) - 清空局部命名空间,触发垃圾回收机制回收模块占用的内存
示例代码
from time import sleep import sys import types def foo(): # 创建独立命名空间,用于exec执行代码 exec_namespace = {} code = """import pandas as pd""" exec(code, exec_namespace) # 筛选本次exec导入的模块,记录真实模块名 imported_modules = [] for name, obj in exec_namespace.items(): if isinstance(obj, types.ModuleType): mod_name = obj.__name__ imported_modules.append(mod_name) # 从sys.modules中移除目标模块 for mod_name in imported_modules: if mod_name in sys.modules: del sys.modules[mod_name] # 清空命名空间,释放内存 exec_namespace.clear() if __name__ == '__main__': foo() sleep(100)
注意事项
- 若模块被其他代码共享(比如函数外也导入了该模块),移除
sys.modules中的模块会导致后续导入重新加载,可能引发异常或性能问题,需根据实际场景判断是否使用 - 对于模块自动导入的子模块(如pandas内部依赖的子模块),上述方法不会自动清理,若需彻底清理需递归遍历模块依赖,但可能引发不可预知的问题,需谨慎操作
内容的提问来源于stack exchange,提问作者XieZhiPeng
相关产品推荐
相关产品推荐

