如何获取已加载文件路径列表及曾加载后移除的模块路径?
如何追踪所有曾加载过的模块文件路径
好问题!你当前用sys.modules配合inspect.getfile()的方法,确实能拿到当前活跃模块的文件路径,但要覆盖那些加载后又从sys.modules中移除的模块,就得从Python的模块加载机制入手——毕竟sys.modules只是当前模块的缓存,模块被删除后这里就没有留存记录了。
下面分享两种可行的思路:
1. 提前Hook模块加载流程(推荐方案)
Python的模块加载是通过sys.meta_path里的查找器(Finder)和加载器(Loader)完成的,我们可以自定义一个追踪器,插入到这个流程里,在模块加载的瞬间就记录下它的文件路径,这样哪怕之后模块被从sys.modules中移除,我们的记录依然保留。
示例代码如下:
import sys import importlib.abc import importlib.util class ModuleLoadTracker(importlib.abc.MetaPathFinder, importlib.abc.Loader): def __init__(self): self.loaded_files = set() # 初始化时先记录当前已加载的所有非内置模块路径 for module in sys.modules.values(): try: if hasattr(module, '__file__') and module.__file__ is not None: self.loaded_files.add(module.__file__) except Exception: # 跳过无法获取路径的模块(比如部分特殊内置模块) pass def find_spec(self, fullname, path, target=None): # 先让默认的查找器处理模块查找,我们只负责记录路径 spec = None for finder in sys.meta_path: if finder is self: continue try: spec = finder.find_spec(fullname, path, target) if spec is not None: break except Exception: continue # 记录有效模块的源文件路径(排除内置模块) if spec and spec.origin is not None and spec.origin != 'built-in': self.loaded_files.add(spec.origin) return spec # 初始化追踪器并插入到meta_path最前面,确保能拦截所有加载请求 tracker = ModuleLoadTracker() sys.meta_path.insert(0, tracker)
使用说明:
- 把这段代码放在你程序的最开头运行,这样就能从程序启动时开始追踪所有模块加载。
- 之后不管你加载、删除多少模块,所有曾被加载过的文件路径都会存在
tracker.loaded_files这个集合里(自动去重)。 - 注意过滤掉了内置模块(它们没有物理文件路径),以及一些无法获取路径的特殊模块。
2. 事后补救:无法追踪已移除的模块
如果是程序已经运行了一段时间,现在才想到要追踪已加载过的模块,那很遗憾——Python本身不会默认保存已移除模块的加载历史,sys.modules里已经没有这些模块的痕迹,也就无法回溯它们的文件路径了。这种情况下只能通过上面的Hook方案,在后续的代码运行中做追踪。
补充:你原有方法的局限性
你之前的代码:
import inspect import sys lizard = list() for mdl in sys.modules.values(): try: lizard.append(inspect.getfile(mdl)) except: pass
只能获取当前存在于sys.modules中的模块,如果模块被通过del sys.modules["module_name"]移除,或者被Python的垃圾回收机制清理,这段代码就拿不到对应的路径了。
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

