2013-01-04 463 views
9

我需要monkeypatch請求的響應類(版本1.0.4,當前爲這個問題),以添加其他方法。Python猴子修補程序

我有這樣的代碼:

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 

當原始響應調用super它失敗() - https://github.com/kennethreitz/requests/blob/master/requests/models.py#L391

我想這是因爲它會很困惑,因爲我已經取代了階級,我覺得像我在做一些愚蠢的事情,有什麼想法?提前致謝。

+0

[2]:請求.__ version__ 出[2]: '1.0.4' 這對你也是如此嗎?此代碼用於爲我工作的舊版本的請求 – user964375

+0

失敗,出現什麼錯誤? – Eloff

+0

文件「/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/models.py」,第391行,在__init__中 super (Response,self).__ init __() TypeError:super(type,obj):obj必須是一個實例或類型的子類型 – user964375

回答

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' 
+0

我知道我們Pythonistas __hate__ OOP,但子類化如何? – tenfishsticks

+0

@tenfishsticks:您仍然必須用該子類替換'Response'類,因爲'requests' API將返回該類的實例。爲了添加一個方法,將該方法添加到現有類中更簡單。 –

4

我不認爲你可以猴子補丁型像那樣。當輸入requests時,所有these模塊都被初始化。由於整個圖書館反覆使用from xy import Request,它將對實際類型有精確的參考。只有在此之後,您纔可以替換模型模塊中的Response類型,以便僅影響後續導入。

除非您瀏覽所有模塊並手動將它們的響應引用替換爲新類型,否則它們仍將使用原始的引用,從而使您的補丁無用。正如Martijn所建議的那樣,您應該保留原始類型,但直接擴展它。

+0

謝謝。我將使用inspect.getmembers從我的類中獲取所有方法,並將它們分配給原始類。略微不太優雅,但會起作用。 – user964375

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