Python猴子修补

时间:2013-01-04 14:25:27

标签: python monkeypatching

我需要monkeypatch请求的Response类(版本1.0.4,此问题的当前版本),以添加其他方法。

我有这段代码:

import requests

class Response(requests.models.Response):
    def hmm(self):
        return 'ok'

requests.models.Response = Response

r = requests.get('http://bbc.co.uk')

print r

当原始Response调用super() - https://github.com/kennethreitz/requests/blob/master/requests/models.py#L391

时失败

我认为这是因为它让我感到困惑,因为我已经取代了课程,我觉得我在做一些愚蠢的事情,任何想法?提前谢谢。

3 个答案:

答案 0 :(得分:12)

你最好直接将你的功能添加到课堂上:

def hmm(self):
    return 'ok'
requests.models.Response.hmm = hmm

这很好用:

>>> import requests
>>> def hmm(self):
...     return 'ok'
... 
>>> requests.models.Response.hmm = hmm
>>> r = requests.get('http://bbc.co.uk')
>>> print r
<Response [200]>
>>> r.hmm()
'ok'
>>> requests.__version__
'1.0.4'

答案 1 :(得分:4)

我认为你不能像那样修补那种类型。导入requests时,将初始化所有these个模块。并且由于整个库一遍又一遍地使用from xy import Request,它将具有对实际类型的精确引用。只有在此之后,才会替换模型模块中的响应类型,因此只会影响后续导入。

除非您通过所有模块并手动将其响应参考替换为新类型,否则它们仍将使用原始模块,使您的补丁无效。

相反,你应该保留原始类型,但是直接扩展它,就像Martijn建议的那样。

答案 2 :(得分:1)

使用setattr快速修复,但它有点难看(但在语义上等同于@Martijn answer):

def hmm(self):
    return 'OK - %s' % self.status_code

setattr(requests.models.Response, 'hmm', hmm)

r = requests.get('http://bbc.co.uk')
print r.hmm()
# prints 
# OK - 200