【问题标题】:practical considerations about backporting a feature from python 3.3 to 2.7 versus monkeypatching关于将功能从 python 3.3 反向移植到 2.7 与猴子补丁的实际考虑
【发布时间】:2012-05-24 23:39:53
【问题描述】:

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

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

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

在 ruby​​ 世界中,monkeypatching 更容易被容忍,但在大多数 python 圈子中,这种危险但经常有用的技术是不受欢迎的。

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

(我对每种方法的优缺点都很感兴趣)

[更新]

pps 实际上,再想一想,我一直认为猴子修补意味着以某种方式就地修改现有类,以便在从标准位置加载时调用新代码(我必须承认,现在我想到了,我有不知道你怎么能做到这一点)。这不是我在这里建议的 - 这个子类将是一个新类,在我自己的模块中,仅由我自己的代码使用。 [安德鲁库克]

安德鲁,感谢您花时间回答。这样我会分叉一些 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,twisted 对于网络代码来说是惊人的,我可以在 2.7 中做任何事情,但需要运行另一个进程。

【问题讨论】:

  • 对不起;我知道这不是一个真正的答案,但这不是 SMTP 的 local_hostname 参数所做的(而且它一直是“永远”的选项)?
  • @andrewcooke:我不这么认为,AFAIK local_hostname 仅用于 helo 和 ehlo 之类的命令(否则名称由 socket.getfqdn 猜测)-但套接字的实际 IP 地址将绑定将由底层操作系统决定。
  • 你说得对,现在我阅读了源代码。

标签: python monkeypatching backport


【解决方案1】:

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

我不完全确定猴子补丁是什么意思(我从未使用过 ruby​​),但我认为以上对于 python 来说是完全正常的。如果您不打算覆盖该方法,那么它将使用前导下划线命名。我自己没有使用过 SMTP,但我使用了 HTTP 库并做了类似的事情来向 HTTP 服务器添加身份验证。这是有偿的、专业的工作,我完全不用担心这样做(简单的 HTTP 服务器不适合大量使用,但在某些情况下很有用)。

(我无法真正提供任何关于利弊的讨论,因为我看不出替代方案是什么 - 你的意思是挖出补丁并应用它吗?我想你可以这样做,但它可能包含很多更多更改 - 如果我知道存在补丁,我可能会快速阅读它以确保它与我正在做的事情一致,但仅此而已。创建一个新的、打补丁的“官方”smtplib 似乎需要做更多的工作没有真正的收获——这不是火箭科学代码,它只是一个绑定参数。)

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

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

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

【讨论】:

    猜你喜欢
    • 2011-08-26
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多