很久之前阅读的,差点忘了
一、_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关于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,让它自动根据传进来的method进行hack(钩子)方式的添加其它类型HTTP请求方式。一般直接使用urllib2,可以如下这样实现其他类型请求:
import urllib2
request = urllib2.Request(uri, data=data)
request.get_method = lambda: 'PUT' # or 'DELETE'
response = urllib2.urlopen(request)
这是我第二次回顾源码前面的细节,真的要仔细看源码和注释才行,之前只是过了一遍。
二、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类型,如果是,就调用自定义的自动选择认证handlers模块,
urllib2中认证相关的处理模块主要有以下几种:
HTTPBasicAuthHandler(password_mgr=None) #处理与远程主机的身份验证
HTTPDigestAuthHandler(password_mgr=None)
ProxyBasicAuthHandler(password_mgr=None) # 处理与代理的身份验证
ProxyDigestAuthHandler(password_mgr=None)
这些处理类都在urllib2中定义,看Requests源码很多时候需要了解urllib2模块的相关功能,需要阅读请到这里Python2 urllib2模块文档 , 需要看该模块的源码的话,可以去Python3 urllib.request模块源码参看源码。
如果没有auth对象,则调用自定义的AuthManager类来注册一个auth对象,关于AuthManager类,里面使用了单例模式,还有重写了 HTTPPasswordMgr类的几个函数,细节请阅读urllib.request模块源码中的HTTPPasswordMgr。
三、_get_opener()函数
handlers的处理都放在这里,要了解这个函数,就必须了解urllib2怎么处理封装Handlers,
Openers对象(一个urllib2.OpenerDirector的实例),如何构建(build_opener)、如何安装全局(install_opener)
(待改进)
四、代码重构
在v0.3.4版本中重构了整个项目,使功能模块更加清晰
0.3.4
+++++
* Urllib2 HTTPAuthentication Recursion fix (Basic/Digest)
* Internal Refactor
* Bytes data upload Bugfix
解决了urllib2模块存在的认证问题,就是输入错误的密码认证,会无限循环认证下去,具体请看urllib2 Recursion issue.再看代码重构后的requests目录下:
# 重构后
requests
├── api.py
├── async.py # moneypatch 猴子补丁
├── core.py
├── __init__.py # contextmanager
├── models.py # 以前core.py中的代码,主要是Request、Response类
├── monkeys.py # 重写urllib2相关类的实现
├── packages # 第三方库,关于上传文件相关的。
│ ├── __init__.py
│ └── poster
│ ├── encode.py
│ ├── __init__.py
│ ├── streaminghttp.py
├── patches.py
└── structures.py # 来自于 werkzeug 的多key字典之类的数据结构
重构前
├── requests
│ ├── async.py
│ ├── core.py # 所有代码都在这里
│ ├── __init__.py # contextmanager
│ ├── packages # 同上
│ │ ├── __init__.py
│ │ └── poster
│ │ ├── encode.py
│ │ ├── __init__.py
│ │ ├── streaminghttp.py
│ └── structures.py
这样的确代码清晰好多,比如重写urllib2的类就可以全部放在monkeys.py,以后需要重写其他标准库的类也同样放在里面,维护起来就方便很多
五、看Pull Request
其实,各种功能讨论和bug修复,都可以在PR里面看到更详细的内容,可以看到那些贡献者的讨论,还是有一点用的吧。。。
发现jgorset这个贡献者很活跃,从版本0.。。。忘了, 就是很早的版本他都不断提交PR,很多代码结构的重构都是他PR上去的,应该是个牛人。
v0.5.0
第五版改动还真是很大啊,搞得我都看得有点懵了,总的来说很多细节方面进行了优化,
测试用例也有很大的改动,统一了测试使用的URL。
未完待续。。。。
网友评论