Requests 源码阅读-Day3
[toc]
hooks
hooks初始化
继续前面的分析,来到了hook这部分
class Session(SessionRedirectMixin):
__attrs__ = [ 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', 'max_redirects', ]
def __init__(self):
#: A case-insensitive dictionary of headers to be sent on each #: :class:`Request <Request>` sent from this #: :class:`Session <Session>`. self.headers = default_headers() print("headers=", self.headers)
#: Default Authentication tuple or object to attach to #: :class:`Request <Request>`. self.auth = None
#: Dictionary mapping protocol or protocol and host to the URL of the proxy #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to #: be used on each :class:`Request <Request>`. self.proxies = {}
#: Event-handling hooks. self.hooks = default_hooks() ....看到调用的是default_hook方法,然后到文件开头可以看到是导入了hooks.py
from .hooks import default_hooks, dispatch_hook到hooks.py这个文件查看:
"""requests.hooks~~~~~~~~~~~~~~
This module provides the capabilities for the Requests hooks system.
Available hooks:
``response``: The response generated from a Request."""HOOKS = ['response']
def default_hooks(): return {event: [] for event in HOOKS}就写了一句话,这是什么意思呢?
通过注释我们知道hooks意为事件挂钩,可以用来操控部分请求过程或者信号事件处理。
requests有一个钩子系统,在请求产生的响应response前,做一些想做的事情。
上述源代码中default_hooks()方法用了字典解析,最后返回{‘response’:[]}。
hooks使用
下面我们简单描述一下hooks是如何使用的。
首先我们需要传递一个字典{hook_name
hook_name为钩子名,也就是 “response”,callback_function为钩子方法,在目标事件发生时回调该方法。
callback_function会接受一个数据块作为它的第一个参数,
定义如下def callback_function(r, *args, **kwargs)。
从default_hooks()方法返回的hooks默认参数{‘response’:[]}
可知,键”response”所对应的值为一个列表
换句话说,对于一个钩子事件,可以有多个钩子方法。
下面我们写个例子演示一下。
>>> def hooks1(r, *args, **kwargs):... print("hooks1 url=" + r.url)...>>> def hooks2(r, *args, **kwargs):... print("hooks2 encoding=" + r.encoding)...>>> hooks = dict(response=[hooks1,hooks2])>>> requests.get("http://httpbin.org", hooks=hooks)hooks1 url=http://httpbin.org/hooks2 encoding=utf-8<Response [200]>cookies
继续往下分析看看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({})这里面的cookiejar_from_dict 到文件开头看是导入cookies.py:
from .cookies import (cookiejar_from_dict, extract_cookies_to_jar,进入cookies.py查看到这个方法:
def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): """Returns a CookieJar from a key/value dictionary.
:param cookie_dict: Dict of key/values to insert into CookieJar. :param cookiejar: (optional) A cookiejar to add the cookies to. :param overwrite: (optional) If False, will not replace cookies already in the jar with new ones. :rtype: CookieJar """ if cookiejar is None: cookiejar = RequestsCookieJar()
if cookie_dict is not None: names_from_jar = [cookie.name for cookie in cookiejar] for name in cookie_dict: if overwrite or (name not in names_from_jar): cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
return cookiejar这里面的RequestsCookieJar()是什么东西?
定位到该文件里面的RequestsCookieJar方法
class RequestsCookieJar(cookielib.CookieJar, MutableMapping):...可以看到这又用到了多继承,继承了cookielib.CookieJar和MutableMapping类,
问题:
1.继承这两个类是做什么用呢?
2.前面的cookiejar = RequestsCookieJar() 究竟执行了什么操作?
分别进行解答: 1.继承这两个类是为了下面调用里面的方法,MutableMapping这个在前面的章节已经分析过了,这里就不在说明
2.RequestsCookieJar() 其实调用了cookielib.CookieJar里面的__init__方法
cookies.py
from .compat import cookielib, urlparse, urlunparse, Morsel, MutableMapping->调用了compat.py里面cookielib , 继续分析调用了http模块里面的cookiejar
...elif is_py3: from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag from urllib.request import parse_http_list, getproxies, proxy_bypass, proxy_bypass_environment, getproxies_environment from http import cookiejar as cookielib然后到http模块里面查看这个cookiejar
http/cookiejar.py 里面
class CookieJar: """Collection of HTTP cookies.
You may not need to know about this class: try urllib.request.build_opener(HTTPCookieProcessor).open(url). """
non_word_re = re.compile(r"\W") quote_re = re.compile(r"([\"\\])") strict_domain_re = re.compile(r"\.?[^.]*") domain_re = re.compile(r"[^.]*") dots_re = re.compile(r"^\.+")
magic_re = re.compile(r"^\#LWP-Cookies-(\d+\.\d+)", re.ASCII)
def __init__(self, policy=None): ....通读了下 大概知道这个模块的作用是管理HTTP的cookie值,存储HTTP请求生成的cookie,向传出的HTTP请求添加cookie的对象
cookies初始化方法cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)的作用是将字典类型的cookies插入到cookiejar中,返回cookiejar。
整个cookie都存储在内存中,CookieJar实例销毁后cookie也将丢失。