Python 3:猴子补丁代码不能通过多处理重新导入
Posted
技术标签:
【中文标题】Python 3:猴子补丁代码不能通过多处理重新导入【英文标题】:Python 3: Monkey-patched code not re-importable by multiprocessing 【发布时间】:2012-09-07 19:07:01 【问题描述】:简介
当模块 A 的函数应该是可导入的时,我如何从模块 B 修补模块 A,以便我可以使用 multiprocessing
标准库包运行模块 A 的函数?
背景
一个客户请求了一个不适用于我们任何其他客户的修补程序,因此我创建了一个新分支并为他们编写了一个单独的模块,以便轻松合并来自主分支的更改。为了保持客户端与预修补程序行为的向后兼容性,我将修补程序实现为应用程序中的可配置设置。因此,我不想替换我的旧代码——只需在设置打开时对其进行修补。我是通过monkey patching 完成的。
代码结构
__main__
模块读取配置文件。如果配置打开了修补程序的开关,__main__
通过用hotfix
模块中定义的代码替换几个函数来修补我的engine
模块——本质上,被替换的函数是key function to a maximization function。 engine
模块稍后会加载一个 multiprocessing
工人池。
问题
一旦multiprocessing
worker 启动,首先multiprocessing
执行re-imports* engine
模块并寻找__main__
试图替换的关键功能(然后multiprocessing
交出控制我的代码并开始最大化算法)。由于engine
正在被一个全新的进程重新导入,并且新进程不会重新运行__main__
(读取配置文件的位置),因为这会导致无限循环,它不知道重新运行猴子补丁engine
.
问题
如何在我的代码中保持模块化(即,将修补程序代码保存在单独的模块中)并仍然利用 Python 的 multiprocessing
包?
* 请注意,我的代码必须在 Windows(为了我的客户端)和 Unix(为了我的理智......)上运行
【问题讨论】:
+1,格式很好的问题。但是multiprocessing
不会在子进程中重新导入__main__
吗?
@nneonneo,是的,但是重新运行 __main__.main()
会导致无限循环。
当然,当然。但是你不能有单独的read_config
和main()
方法,并调用read_config
而不是main()
?
我如何让__main__
确定它是作为multiprocessing
工作人员还是从命令行加载的?
看我的回答。我相信这应该为你做。
【参考方案1】:
这听起来像是猴子修补不起作用的地方。将相关功能提取到单独的模块并让引擎从那里导入它们更容易。也许您可以对从何处导入它们进行配置设置。
另一种模块化的方法是使用某种组件架构,例如ZCA。最后一个选项是我会选择的,但那是因为我已经习惯了,所以对我来说没有额外的学习。
【讨论】:
【参考方案2】:要使其在具有fork()
的 UNIX/Linux 操作系统上运行,您无需执行任何特殊操作,因为新进程可以访问与父进程相同的(猴子补丁)类。
要使其在 Windows 上运行,请让您的 __main__
模块在导入时读取配置(将 read_config
/patch_engine
调用置于全局范围内),但在 if __name__ == '__main__'
中执行多处理(引擎执行)守卫。
然后,无论何时导入 __main__
(从命令行或从 multiprocessing
重新导入),都会执行读取配置代码,但仅当从命令行(因为__main__
在子进程中以不同的名称重新导入)。
【讨论】:
【参考方案3】:听起来您将不得不修改 engine.py
以检查配置文件,并在需要时自行修补。
要同时在 unix 和 Windows 上工作,engine
可以保留一个全局 CONFIG_DONE
变量来决定是否需要再次检查配置文件。
【讨论】:
以上是关于Python 3:猴子补丁代码不能通过多处理重新导入的主要内容,如果未能解决你的问题,请参考以下文章