将所有模块的名称存储在 python 解释器开始使用的 sys.modules 中,然后在请求时从 sys.modules 中删除所有新模块。这似乎使解释器准备重新导入相同的模块,即使它之前已经导入了它们。
在某些情况下可以使模块重新加载强制方法起作用,但它有点麻烦。总之:
您需要确保所有相互依赖的模块都立即重新加载。因此,任何执行“import y”或“from y import ...”的模块“x”都必须与模块“y”同时从 sys.modules 中删除。
如果您的应用程序或任何其他活动模块正在使用线程,则此过程将需要锁定保护。
任何在其他模块中留下指向自身的钩子的模块都无法有效地重新加载,因为对旧模块的引用将保留在未重新加载/不可重新加载的代码中。这包括异常钩子、信号、警告过滤器、编码、猴子补丁等。如果您开始愉快地重新加载包含其他人代码的模块,您可能会惊讶于他们这样做的频率,这可能会导致微妙和奇怪的错误。
所以要让它工作,你需要在相互依赖的模块之间有明确定义的边界——“它是在初始启动时导入的”可能还不够好——并确保它们被很好地封装而没有意外的依赖关系,比如猴子补丁。
这可以基于文件夹,因此例如 /home/me/myapp/lib 中的任何内容都可以作为一个单元重新加载,同时不理会其他模块 - 尤其是例如 stdlib 中的内容。/usr/lib/python2.x/ 通常不可靠地重新加载。如果需要,我在尚未发布的 webapp 重新加载包装器中提供了此代码。
最后:
- 您需要了解一些关于 sys.modules 的内部结构,特别是它会留下一堆“无”值来表示相对导入失败。如果您没有在删除其他模块值的同时删除它们,则后续导入模块的尝试可能(有时)最终导入“无”,从而导致令人困惑的错误。
这是一个令人讨厌的实现细节,可能会在未来的某个 Python 版本中改变和破坏您的应用程序,但这是以不受支持的方式使用 sys.modules 的代价。