【发布时间】:2012-08-12 05:14:45
【问题描述】:
在 Python 中,术语monkey patch 仅指在运行时对类或模块的动态修改,作为初学者,我真的很难在 python 的上下文中理解这个术语。谁能用一个真实的例子向我解释一下我们到底是怎么做的?
- 类的动态修改
- 在运行时动态修改模块
我坚持一个真实世界的例子(尽可能简单)来了解我们必须在哪些场景中执行此类任务?
【问题讨论】:
标签: python monkeypatching
在 Python 中,术语monkey patch 仅指在运行时对类或模块的动态修改,作为初学者,我真的很难在 python 的上下文中理解这个术语。谁能用一个真实的例子向我解释一下我们到底是怎么做的?
我坚持一个真实世界的例子(尽可能简单)来了解我们必须在哪些场景中执行此类任务?
【问题讨论】:
标签: python monkeypatching
Monkey-patching 是一种在现有代码将继续运行但行为已修改的情况下进行一些全局底层更改的方法。
str命令行为的非常简单的例子:b.py
def foo(msg):
s = str(msg)
print s, type(s)
a.py
import b
b.foo('foo')
# monkey-patch
import __builtin__
__builtin__.str = unicode
b.foo('foo')
# Results:
#foo <type 'str'>
#foo <type 'unicode'>
a 模块使用str 命令修改了其他代码的行为,将其修补为使用unicode。这是必要的,因为我们假装我们无法访问b.py 的代码。它可能是一个巨大的包,我们只是使用而无法更改。但是我们可以插入新的代码来改变行为。
>>> import gevent >>> from gevent import socket >>> urls = ['www.google.com', 'www.example.com', 'www.python.org'] >>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls] >>> gevent.joinall(jobs, timeout=2) >>> [job.value for job in jobs] ['74.125.79.106', '208.77.188.166', '82.94.164.162']上面的示例使用 gevent.socket 进行套接字操作。如果 使用标准插座模块,需要 3 倍的时间才能完成 完成,因为 DNS 请求将是连续的。使用 greenlets 中的标准套接字模块使 gevent 变得毫无意义, 那么构建在 socket 之上的模块和包呢?
这就是猴子修补的目的。 gevent.monkey 中的函数 小心替换标准套接字模块中的函数和类 与他们的合作伙伴。这样即使是模块 不知道 gevent 可以从在 multi-greenlet 中运行中受益 环境。
>>> from gevent import monkey; monkey.patch_socket() >>> import urllib2 # it's usable from multiple greenlets now
【讨论】:
使用猴子补丁时有一些现实生活中的例子:
Object.method1() 的行为。方法可以返回一个字符串或无。所以这里的猴子补丁来了。您将method1 替换为仅包含一行代码return None 的存根方法。setattr 函数在 Python 中轻松完成。嗯,这通常意味着您的应用程序架构不佳,并且不是一个好的设计决策。【讨论】: