requests库基于urllib3库改写

init.py是模块中极为重要的一点,它把一个简单的文件夹转换成了一个模块,这样的话,不同文件之间就可以相互导入了.init实际上是initial初始化的意思,导入包之后它,会常驻,自动运行!!!!

简单分析一下_init_.py(仅仅是初始化整个包而已,不用深究)

import urllib3
import chardet
import warnings
from .exceptions import RequestsDependencyWarning


def check_compatibility(urllib3_version, chardet_version):
    urllib3_version = urllib3_version.split('.')
    assert urllib3_version != ['dev']  # Verify urllib3 isn't installed from git.

    # Sometimes, urllib3 only reports its version as 16.1.
    if len(urllib3_version) == 2:
        urllib3_version.append('0')

    # Check urllib3 for compatibility.
    major, minor, patch = urllib3_version  # noqa: F811
    major, minor, patch = int(major), int(minor), int(patch)
    # urllib3 >= 1.21.1, <= 1.22
    assert major == 1
    assert minor >= 21
    assert minor <= 22

    # Check chardet for compatibility.
    major, minor, patch = chardet_version.split('.')[:3]
    major, minor, patch = int(major), int(minor), int(patch)
    # chardet >= 3.0.2, < 3.1.0
    assert major == 3
    assert minor < 1
    assert patch >= 2


# Check imported dependencies for compatibility.
try:
    check_compatibility(urllib3.__version__, chardet.__version__)
except (AssertionError, ValueError):
    warnings.warn("urllib3 ({0}) or chardet ({1}) doesn't match a supported "
                  "version!".format(urllib3.__version__, chardet.__version__),
                  RequestsDependencyWarning)

# Attempt to enable urllib3's SNI support, if possible
try:
    from urllib3.contrib import pyopenssl
    pyopenssl.inject_into_urllib3()
except ImportError:
    pass

# urllib3's DependencyWarnings should be silenced.
from urllib3.exceptions import DependencyWarning
warnings.simplefilter('ignore', DependencyWarning)

from .__version__ import __title__, __description__, __url__, __version__
from .__version__ import __build__, __author__, __author_email__, __license__
from .__version__ import __copyright__, __cake__

from . import utils
from . import packages
from .models import Request, Response, PreparedRequest
from .api import request, get, head, post, patch, put, delete, options
from .sessions import session, Session
from .status_codes import codes
from .exceptions import (
    RequestException, Timeout, URLRequired,
    TooManyRedirects, HTTPError, ConnectionError,
    FileModeWarning, ConnectTimeout, ReadTimeout
)

# Set default logging handler to avoid "No handler found" warnings.
import logging
try:  # Python 2.7+
    from logging import NullHandler
except ImportError:
    class NullHandler(logging.Handler):
        def emit(self, record):
            pass

logging.getLogger(__name__).addHandler(NullHandler())

# FileModeWarnings go off per the default.
warnings.simplefilter('default', FileModeWarning, append=True)
解释一下导入包的方式,from 一个.是导入当前目录的,两个.是导入上一层目录.
导入包之后,_init\.py会自动运行,assert作用是保证可用性(如果不确定某个式子,可以先用assert,如果不符合会报错,如assert 12=12,参考[\_[_http://www.iplaypy.com/jinjie/assert.html](http://www.iplaypy.com/jinjie/assert.html)_\]\(\[_[http://www.iplaypy.com/jinjie/assert.html\)\](http://www.iplaypy.com/jinjie/assert.html%29\)\),整体就是判断urllib版本.\_\]\([http://www.iplaypy.com/jinjie/assert.html\)\_\),整体就是判断urllib版本.\_](http://www.iplaypy.com/jinjie/assert.html%29_%29,整体就是判断urllib版本._)\)

最后探究一下代码的基本流程兼总结

整个requests库的关键在于sessions.py,这是处理各种数据的关键之处,逃也逃不开
首先看几段代码
import requests
s=requests.session()       #如果没有的话,s就不会永久保存
data={"Login.Token1": "41651Xxx", "Login.Token2":"xxxxxx"}
s.post("http://erp.njcit.cn/userPasswordValidate.portal",data=data)#传入密码用post,传入header包含cookie用get..
print(s.get("http://erp.njcit.cn/index.portal?.pn=studyCenter_p2107_p4581").text)
看流程:首先requests.session()

跳入

这是个关键,也涉及了python类的概念,事实上,python类和java类是一毛一样的
public class Dog extends Animal {             #采用了继承
    myid=10;
    public Dog(String myName, int myid) {        #构造方法
        xx;
    } 
    public static void main(String []args){}      #作为类的话可有可无,一般没有
    public static void xx(){                  #方法
    }
}
其实python强大的地方就很明显了,开头class session(xx),这括号里面的内容是必须有的,强迫继承,当然可以基础object(最初的样子),所以说事实上调用这个类的时候session()括号里面的内容是由构造函数(init函数)决定,当然无论构造函数怎么样,session括号都可以为空!!!!并且构造函数自动被调用.
查看init函数
  def __init__(self):
        self.headers = default_headers()
        self.auth = None
        self.proxies = {}
        self.hooks = default_hooks()
        self.params = {}
        self.stream = False
        self.verify = True
        self.cert = None
        self.max_redirects = DEFAULT_REDIRECT_LIMIT
        self.trust_env = True
        self.cookies = cookiejar_from_dict({})
        self.adapters = OrderedDict()
        self.mount('https://', HTTPAdapter())
        self.mount('http://', HTTPAdapter())
s=requests.session() 中,把右边的类对象理解为一个堆,通过init函数把类似与cookie,headers之类的初始化了,实际上就是板上钉钉了,一直存在,除非被修改.
下次通过s.post实际上就跳到了session类的post方法了(当然像get,delete,put都有)

然后跳到同一个类的request方法,查看request方法(这一步是绝对的关键,再怎么强调都不为过,而且这个才是函数进行最关键区域,每个请求都会经过)

d,ef request(self, method, url,
            params=None, data=None, headers=None, cookies=None, files=None,
            auth=None, timeout=None, allow_redirects=True, proxies=None,
            hooks=None, stream=None, verify=None, cert=None, json=None):

        req = Request(
            method=method.upper(),
            url=url,
            headers=headers,
            files=files,
            data=data or {},
            json=json,
            params=params or {},
            auth=auth,
            cookies=cookies,
            hooks=hooks,
        )
        prep = self.prepare_request(req)

        proxies = proxies or {}

        settings = self.merge_environment_settings(
            prep.url, proxies, stream, verify, cert
        )

        send_kwargs = {
            'timeout': timeout,
            'allow_redirects': allow_redirects,
        }
        send_kwargs.update(settings)
        resp = self.send(prep, **send_kwargs)

        return resp

results matching ""

    No results matching ""