美文网首页
Requests源码阅读

Requests源码阅读

作者: guoweikuang | 来源:发表于2019-09-26 21:19 被阅读0次
    image

    很久之前阅读的,差点忘了


    一、_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。
    
    

    未完待续。。。。

    相关文章

      网友评论

          本文标题:Requests源码阅读

          本文链接:https://www.haomeiwen.com/subject/ynwnuctx.html