很久之前閱讀的,差點忘了
一、_Requests模塊的作用
class _Request(urllib2.Request):
"""Hidden wrapper around the urllib2.Request object. Allows for manual
setting of HTTP methods.
"""
def __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None):
urllib2.Request.__init__(self, url, data, headers, origin_req_host, unverifiable)
self.method = method
def get_method(self):
if self.method:
return self.method
return urllib2.Request.get_method(self)
剛開始看時,不太注意注釋里面的英文,然后就看它作用是繼承urllib2.Request模塊并改寫一下get_method(),這里就有點迷糊了,改寫get_method()作用是什么。
于是去看了urllib2關(guān)于get_method()的文檔,文檔就一句話就沒有怎么留意,下面是文檔原話:
Request.get_method()
Return a string indicating the HTTP request method. This is only meaningful for HTTP requests, and currently always returns 'GET' or 'POST'.
這句話說的是,返回一個指示HTTP請求的方法。只對HTTP請求有效,目前總是返回'GET'或者'POST'。使用過Requets的人都知道,Requests不僅僅有GET和POST請求,還有HEAD、POST、DELETE等請求,所以這里重寫了get_method,讓它自動根據(jù)傳進來的method進行hack(鉤子)方式的添加其它類型HTTP請求方式。一般直接使用urllib2,可以如下這樣實現(xiàn)其他類型請求:
import urllib2
request = urllib2.Request(uri, data=data)
request.get_method = lambda: 'PUT' # or 'DELETE'
response = urllib2.urlopen(request)
這是我第二次回顧源碼前面的細節(jié),真的要仔細看源碼和注釋才行,之前只是過了一遍。
二、Reqeusts中的認證模塊
if isinstance(auth, (list, tuple)):
auth = AuthObject(*auth)
if not auth:
auth = auth_manager.get_auth(self.url)
self.auth = auth
判斷auth是否list或者tuple類型,如果是,就調(diào)用自定義的自動選擇認證handlers模塊,
urllib2中認證相關(guān)的處理模塊主要有以下幾種:
HTTPBasicAuthHandler(password_mgr=None) #處理與遠程主機的身份驗證
HTTPDigestAuthHandler(password_mgr=None)
ProxyBasicAuthHandler(password_mgr=None) # 處理與代理的身份驗證
ProxyDigestAuthHandler(password_mgr=None)
這些處理類都在urllib2中定義,看Requests源碼很多時候需要了解urllib2模塊的相關(guān)功能,需要閱讀請到這里Python2 urllib2模塊文檔 , 需要看該模塊的源碼的話,可以去Python3 urllib.request模塊源碼參看源碼。
如果沒有auth對象,則調(diào)用自定義的AuthManager類來注冊一個auth對象,關(guān)于AuthManager類,里面使用了單例模式,還有重寫了 HTTPPasswordMgr類的幾個函數(shù),細節(jié)請閱讀urllib.request模塊源碼中的HTTPPasswordMgr。
三、_get_opener()函數(shù)
handlers的處理都放在這里,要了解這個函數(shù),就必須了解urllib2怎么處理封裝Handlers,
Openers對象(一個urllib2.OpenerDirector的實例),如何構(gòu)建(build_opener)、如何安裝全局(install_opener)
(待改進)
四、代碼重構(gòu)
在v0.3.4版本中重構(gòu)了整個項目,使功能模塊更加清晰
0.3.4
+++++
* Urllib2 HTTPAuthentication Recursion fix (Basic/Digest)
* Internal Refactor
* Bytes data upload Bugfix
解決了urllib2模塊存在的認證問題,就是輸入錯誤的密碼認證,會無限循環(huán)認證下去,具體請看urllib2 Recursion issue.再看代碼重構(gòu)后的requests目錄下:
# 重構(gòu)后
requests
├── api.py
├── async.py # moneypatch 猴子補丁
├── core.py
├── __init__.py # contextmanager
├── models.py # 以前core.py中的代碼,主要是Request、Response類
├── monkeys.py # 重寫urllib2相關(guān)類的實現(xiàn)
├── packages # 第三方庫,關(guān)于上傳文件相關(guān)的。
│ ├── __init__.py
│ └── poster
│ ├── encode.py
│ ├── __init__.py
│ ├── streaminghttp.py
├── patches.py
└── structures.py # 來自于 werkzeug 的多key字典之類的數(shù)據(jù)結(jié)構(gòu)
重構(gòu)前
├── requests
│ ├── async.py
│ ├── core.py # 所有代碼都在這里
│ ├── __init__.py # contextmanager
│ ├── packages # 同上
│ │ ├── __init__.py
│ │ └── poster
│ │ ├── encode.py
│ │ ├── __init__.py
│ │ ├── streaminghttp.py
│ └── structures.py
這樣的確代碼清晰好多,比如重寫urllib2的類就可以全部放在monkeys.py,以后需要重寫其他標(biāo)準(zhǔn)庫的類也同樣放在里面,維護起來就方便很多
五、看Pull Request
其實,各種功能討論和bug修復(fù),都可以在PR里面看到更詳細的內(nèi)容,可以看到那些貢獻者的討論,還是有一點用的吧。。。
發(fā)現(xiàn)jgorset這個貢獻者很活躍,從版本0.。。。忘了, 就是很早的版本他都不斷提交PR,很多代碼結(jié)構(gòu)的重構(gòu)都是他PR上去的,應(yīng)該是個牛人。
v0.5.0
第五版改動還真是很大啊,搞得我都看得有點懵了,總的來說很多細節(jié)方面進行了優(yōu)化,
測試用例也有很大的改動,統(tǒng)一了測試使用的URL。
未完待續(xù)。。。。