Requests 源码学习笔记

来源:互联网 发布:弹歌软件 编辑:程序博客网 时间:2024/06/04 01:01

Requests 源码学习笔记

Requests是一个Python HTTP库, 由Kenneth Reitz大神编写,具体用法可参考官方文档

开发哲学 PEP20

The Zen of Python

  • Beautiful is better than ugly.(美丽优于丑陋)
  • Explicit is better than implicit.(显式优于隐式)
  • Simple is better than complex.(简单优于复杂)
  • Complex is better than complicated.(复杂优于繁琐)
  • Readability counts.(可读性非常重要)

requests.models 模块

这个模块包含了最重要的对象, 为整个Requests提供支持

RequestEncodingMixin类 & RequestHooksMixin类:

基类,前者与http字节编码有关,后者与回调hooks有关

  • RequestHooksMixinRequest 的基类
  • RequestHooksMixinRequestEncodingPreparedRequest的基类

Request类

class Request(RequestHooksMixin):
用户可以通过Request类来创建一个请求对象,通常使用prepare()来创建一个PreparedRequest实例,这个实例将被发送给服务器.

__init__

 def __init__(self,            method=None, url=None, headers=None, files=None, data=None,            params=None, auth=None, cookies=None, hooks=None, json=None):
  • method: HTTP方法
  • url: URL
  • headers: 要发送的头部字典
  • files: 文件字典{filename: fileobject},多部分上传的文件(文件分块上传)字典
  • data: 被附加在请求上面的实体.当data是字典类型时,将会使用表单编码(form-encoding)
  • json: 当files和data没有被指明时,被附加在请求上面的json
  • params: 字典类型的URL参数,将会被添加到URL后面
  • auth: 认证处理句柄,或者是(user, pass)tuple
  • cookies: 被附加在请求上面的字典或者CookieJar
  • hooks: callback hooks的字典

上述对于属性的赋值采用了如下,类似于c++三元操作符的功能

data = []if data is None else data
    def prepare(self):        """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it."""        p = PreparedRequest()        p.prepare(            method=self.method,            url=self.url,            headers=self.headers,            files=self.files,            data=self.data,            json=self.json,            params=self.params,            auth=self.auth,            cookies=self.cookies,            hooks=self.hooks,        )        return p

PreparedRequest类

class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
包含了精确的字节(bytes),这些将会被发送到服务器.可以通过手工或者Request类来进行构造获取.

requests.session 模块

这个模块提供了一个Session对象用来在不同的请求中管理和持久化设置(cookies, auth, proxies)

import requestsrequests.get('example.com')

函数调用过程如下: request(module)->api.get()->session.request(method='GET')

Session类

一个请求的会话,提供了cookie持久化,连接池,配置 (cookie persistence, connection-pooling and configuration)

基础用法:

import requestss = requests.Session()s.get('http://httpbin.org/get')

使用上下文管理器

with requests.Session() as s:    s.get('http://httpbin.org/get')

定义了__enter____exit__ 是为了实现支持with,上下文管理器

def prepare_request(self, request):通过request(Request)来构造一个PreparedRequest实例并返回

def send(self, request, **kwargs): 发送一个给定的PreparedRequest实例

包含如下操作:

  • 设置初始化参数,和一些必需的变量
  • 设置重定向和分发hook
  • 获得合适的适配器adapter
  • 通过适配器发送请求
  • 获得请求结束时间
  • 设置响应的hooks
  • 持久化cookies
  • 解决重定向的问题
  • 返回响应
        #: A CookieJar containing all currently outstanding cookies set on this        #: session. By default it is a        #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but        #: may be any other ``cookielib.CookieJar`` compatible object.        self.cookies = cookiejar_from_dict({})

session 中cookie的设置如上,cookies可以设置为其他的类型如cookielib.LWPCookieJar,cookie有如下注意点

  • http包里 cookiejar.py 模块
  • LWPCookieJar: 保存一系列的Set-Cookie3的行
    • save(): 保存一系列cookie到文件中
    • LWPCookieJar 继承自 FileCookieJar
    • FileCookieJar 继承自 基类CookieJar

requests.adapters 模块

这个模块包含了Requests用来定义和保持连接传输适配器,使用urllib3作为支撑.

Requests 使用urllib3 去管理连接和其他的feature
复用的连接是保证Http反复请求的一个重要的因素

class BaseAdapter(object):    def __init__(self):        super(BaseAdapter, self).__init__()    def send(self, request, stream=False, timeout=None, verify=True,             cert=None, proxies=None):              raise NotImplementedError    def close(self):        raise NotImplementedError

BaseAdapter: 基类传输适配器, 定义了sendclose函数,如果没有实现则会出现异常.

HttpAdapter: 派生类是对于urllib3的built-in HTTP Adapter (Adapter的概念参考c++/STL Adapter)

http_adapter

重要函数介绍:

    def __init__(self, pool_connections=DEFAULT_POOLSIZE,                 pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES,                 pool_block=DEFAULT_POOLBLOCK):
  • pool_connectins: urllib3 连接池中缓存的连接数,即可复用的连接数,(keep-alive)的数量
  • pool_maxsize: 保存在连接池中连接数的最大值
  • max_retries: 每条连接可以重试的最大次数,注意,仅仅应用在DNS查询超时,socket连接失败,连接超时的情况
  • pool_block: 连接池是否为连接锁定(Block)
def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None):

send:发送一个PreparedRequest实例,返回Response实例

其中包含如下几个函数:

  • get_connection(self, url, proxies=None): 通过代理或不通过代理进行连接,返回urllib3.ConnectionPool

requests.hooks 模块

这个模块给Requests hooks system提供了能力支持

hooks 定义: Essentially it’s a place in code that allows you to tap in to a module to either
provide different behavior or to react when something happens.

hooks:是一小部分代码,允许在模块中监听去提供不同的方法,或者当某一个事情发生时做出反应.

callback 定义: 将函数作为参数传入,当发生了某一个事件,或者某个函数完成时,调用callback function, 回调函数通常是I/O call或者GUI call

模块代码如下:

HOOKS = ['response']def default_hooks():    return dict((event, []) for event in HOOKS)# TODO: response is the only onedef dispatch_hook(key, hooks, hook_data, **kwargs):    """Dispatches a hook dictionary on a given piece of data."""    hooks = hooks or dict()    hooks = hooks.get(key)    if hooks:        if hasattr(hooks, '__call__'):            hooks = [hooks]        for hook in hooks:            _hook_data = hook(hook_data, **kwargs)            if _hook_data is not None:                hook_data = _hook_data    return hook_data

requests.api 模块

这个模块实现了Requests的API

def request(method, url, **kwargs):def get(url, params=None, **kwargs):def options(url, **kwargs):def head(url, **kwargs):def post(url, data=None, json=None, **kwargs):def put(url, data=None, **kwargs):def patch(url, data=None, **kwargs):def delete(url, **kwargs):
原创粉丝点击