关于将一个特性从python 3.3反向移植到2.7而不是monkeypatching的实际考虑

时间:2012-05-24 23:39:54

标签: python monkeypatching backport

我对python3.3中引入的新smtplib功能感兴趣:能够绑定到multihomed计算机(或具有多个IP地址的计算机)中的特定IP地址。

我想使用的许多构建块没有移植到3.3或者端口非常不稳定,所以仅仅因为这个功能而使用3.3的想法是不切实际的。

为了向后移植此功能,我可以修补或monkeypatch。我倾向于将smtplib.SMTP和monkeypatch子类化为底层套接字,因为它简化了部署,似乎不太可能影响基类,并且比政治上正确的反向端口更容易。

在红宝石世界中,monkeypatching更容忍,但在大多数python圈子中,这种危险但却经常使用的技术是不受欢迎的。

我的问题是:你有没有遇到过这样的决定和/或想分享一些建议?

(我对每种方法的利弊感兴趣)

[更新]

  pps实际上,在考虑更多,我总是假设猴子修补意味着以某种方式修改现有的类,以便从标准位置加载时调用新代码(我必须承认,现在我想到它,我有不知道你怎么能这样做)。这不是我在这里建议的 - 这个子类将是一个新类,在我自己的模块中,仅由我自己的代码使用。 [andrew cooke]

安德鲁,谢谢你花时间回答。这样我就会分配一些SMTP.connect代码,并且它也不赞成,因为当原始库更新时,我的分叉代码将不会包含更改。我认为mokeypatching是一种更外科的东西,但如果对monkeypatched代码进行任何重构,这些更新也有可能破坏代码。无论是分叉还是将我的绝地大师都打造成怪物,他们就是黑暗的一面。 : - )

[更新]

最后我写了一个SMTP代理,它接受扩展的EHLO语法,允许选择传出的IP地址:

s = SMTP('localhost', 8025)
# will use 173.22.213.16 as the outgoing IP address
s.ehlo('example.com 173.22.213.16') 

使用twisted它低于40 SLOC,扭曲对于网络代码来说是惊人的,我可以在2.7中做所有事情,但代价是运行另一个进程。

1 个答案:

答案 0 :(得分:1)

我要做的是将SMTP子类化,并将SMTP.connect()方法替换为几乎相同的方法,但使用source_address调用self.sock.connect()(并设置一个额外的参数)。

我不完全确定猴子修补意味着什么(我从未使用过红宝石),但我认为以上对于python来说是完全正常的。如果您不能覆盖该方法,那么它将以前导下划线命名。我自己还没有使用过SMTP,但是我已经使用了HTTP lib并且做了类似的事情来为HTTP服务器添加身份验证。这是付费的,专业的工作,我不担心这样做(简单的HTTP服务器不是用于大量使用,但在某些情况下它很有用)。

(我无法真正提供任何利弊讨论,因为我不知道替代方案是什么 - 你的意思是挖出补丁并应用它吗?我想你可以这样做,但是它可能包含更多更改 - 如果我知道存在补丁,我可能会快速阅读以确保它与我正在做的一致,但这就是全部。创建一个新的,修补的,&#34官方" smtplib似乎更多的工作没有真正的收获 - 这不是火箭科学代码,它只是一个绑定参数。)

ps我会提供任何额外的参数和一个有用的默认值,这样如果用旧代码调用,调用仍然有效。

source of SMTP, although i am unsure what version; socket docs; smtplib docs

pps实际上,在考虑更多,我总是假设猴子修补意味着以某种方式修改现有的类就地,以便从标准位置加载时调用新代码(我必须承认,现在我想一想,我不知道你怎么能这样做)。这是我在这里建议的内容 - 这个子类将是一个新类,在我自己的模块中,仅由我自己的代码使用。