随着时间的推移,我发现需要覆盖Python中的几个stdlib
方法,以克服限制或添加一些缺少的功能。
在所有情况下,我都添加了一个包装函数,并用我的包装器替换了模块中的原始方法(包装器调用了原始方法)。
为什么我这样做?只是为了确保对该方法的所有调用都使用我的新版本,即使这些调用是从其他第三方模块调用的。
我知道 monkeypatching 可能是一件坏事,但我的问题是,如果你小心使用它,是否有用?意思是:
示例:
os.system()
或subprocess.Popen()
添加日志记录支持 - 让您输出到控制台或/并重定向到另一个文件。os.chown()
或os.lchown()
。像我这样的事情在我看来是不错的覆盖,但我想看看其他人是如何看待他们的,特别是应该被视为可接受的monkeypatch,什么不是。
答案 0 :(得分:7)
这些似乎没有需要 monkeypatching。所有这些似乎都有更好,更强大和可靠的解决方案。
添加日志处理程序很简单。没有monkeypatch。
以这种方式完成修复。
from io import open
这很容易。没有补丁。
登录os.system()
?我认为一个简单的“包装器”功能远比复杂的补丁更好。此外,我使用subprocess.Popen
,因为这是推荐的替代品。
添加缺失方法来掩盖操作系统差异(如os.chown()
)似乎更适合try / except。但那只是我。我喜欢明确而非隐含。
总的来说,我仍然看不出明白的好理由。
我讨厌被锁定在遗留代码中(例如os.system
),因为我过于依赖我的monkeypatches。
“子类”的概念适用于模块和类。您可以轻松编写自己的模块,这些模块(a)导入和(b)扩展现有模块。然后,您使用新模块,因为它们提供了额外的功能。你不需要monkeypatch。
即使这些是从其他第三方模块调用的
可怕的想法。您可以通过更改内置功能轻松打破另一个模块。如果您已阅读其他模块并确定,那么monkeypatches将不会中断,那么您所发现的就是这个。
“其他”模块应该有自定义空间。它应该有一个“依赖注入”或策略设计模式的地方。好想法。
找到后,可以修复“其他”模块以允许此自定义。它可能像解释如何修改对象的文档更改一样简单。它可能是一个额外的 用于插入自定义的构造参数。
然后,您可以向作者提供修订后的模块,看看他们是否支持您对其模块的小更新。许多课程可以使用额外的帮助来支持“依赖注入”或策略设计扩展。
如果你还没有读过其他模块而且确定你的monkeypatches工作......那么......我们仍然希望monkeypatches不会破坏任何东西。
答案 1 :(得分:3)
Monkeypatching可能是“最少的邪恶”,有时候 - 大多数情况下,当您需要测试使用不是为可测试性而设计的子系统的代码时(不支持依赖注入& c)。在这些情况下,你将在你的测试工具中进行monkeypatching(非常暂时,幸运),并且为了隔离测试(即,使它们进行单元测试而不是集成测试),几乎总是使用模拟或伪装进行monkeypatching。
这个“糟糕但可能更糟”的用例似乎不适用于您的示例 - 通过编辑应用程序级代码来调用适当的包装函数(比如myos.chown
而不是例如,裸os.chown
并将您的包装函数放在您自己的中间模块(例如myown
)中,这些模块位于应用程序级代码和标准库之间(或者您是第三方扩展)因此包装 - 在这方面标准库没什么特别的。)
当“应用程序级代码”实际上不在您的控制之下时,可能会出现一个有问题的情况 - 它是您不想修改的第三方子系统。尽管如此,我发现在这种情况下,修改第三方子系统以调用包装器(而不是直接使用标准库函数)从长远来看效率更高 - 当然你将更改提交给第三方的维护者有问题的子系统,他们将您的更改推送到他们子系统的下一个版本,并且每个人的生活变得更好(包括在内,因为一旦您的更改被接受,他们将被其他人定期维护和测试! - )
(作为旁注,这样的包装器也可能值得提交为标准库的差异,但 是一个不同的情况,因为标准库的发展非常缓慢和谨慎,特别是在Python 2系列上永远不会再发展,因为2.7是该行的最后一行而且它的功能被冻结了。
当然,所有这些都预示着开源文化。如果出于一些神秘的原因,你使用的是一个闭源第三方子系统,因此你无法维护它,那么你处于另一种情况,猴子补丁可能是较小的邪恶(但这只是因为失去战略控制的邪恶)通过信任你不可能维护的代码,你的开发本身就是一个更大的邪恶;-)。我从来没有发现自己处于这种情况下的第三方软件包既是封闭源代码又是用Python编写的(如果后一种条件不能保存你的monkeypatches就不会对你好; - )。
请注意,这里“闭源”的工作定义非常严格:例如,甚至Microsoft 12年前分发的源代码库,如MFC和Visual C ++(因为他们的产品被称为) - 已关闭-source因为你无法重新发布他们的来源,但是,你仍然有DID手头的资源,所以当你遇到一些可怕的限制或错误时你可以修复它(并将更改提交给他们以供将来的版本发布,以及发布你的变化只是一个差异,只要它绝对不包括他们受版权保护的代码 - 不是微不足道的,而是可行的。)
Monkeypatching远远超出了严格的限制范围,在这种范围内,这种方法是“最不邪恶的”,这是动态语言用户经常犯的错误 - 小心不要自己陷入陷阱!