request 学习笔记
python distribution
from distutils.core import setup- 创建同模块名的目录
- 创建setup.py
- build 打包
$python setup sdist - 安装 python setup install
会自动把模块按照的python 默认环境中 - 使用时 如下123456(1) 只要把你所要打包的module的py文件放到目录下,书写相应的setup.py,(2)执行python setup.py sdist 打包(3)扔到对应机器上 解包(4)python setup.py build(5)sudo python setup.py install【同安装第三方模块步骤】
测试
12test_requests.pyimport unittestrequest.get
1234567891011121314151617181920212223242526272829303132333435363738def __setattr__(self, name, value):if (name == 'method') and (value):if not value in self._METHODS:raise InvalidMethod()object.__setattr__(self, name, value)## 调用对象 可以很方便的给对象的属性赋值## 特殊的属性 只接受 指定的值+ urllib2.urlopen+ StringIO因为StringIO 的操作方式和 file的api很像,所以可以使用StringIO作为文件的 buffer 到一定量之后一次写入示例: https://pymotw.com/2/StringIO/``` python# Find the best implementation available on this platformtry:from cStringIO import StringIOexcept:from StringIO import StringIO# Writing to a bufferoutput = StringIO()output.write('This goes into the buffer. ')print >>output, 'And so does this.'# Retrieve the value writtenprint output.getvalue()output.close() # discard buffer memory# Initialize a read bufferinput = StringIO('Inital value for read buffer')# Read from the bufferprint input.read()文件上传
Python中使用POST方式上传文件 : (http://oldj.net/article/python-upload-file-via-form-post/)
使用 python的 poster模块
12345678910111213141516171819# test_client.pyfrom poster.encode import multipart_encodefrom poster.streaminghttp import register_openersimport urllib2# 在 urllib2 上注册 http 流处理句柄register_openers()# 开始对文件 "DSC0001.jpg" 的 multiart/form-data 编码# "image1" 是参数的名字,一般通过 HTML 中的 <input> 标签的 name 参数设置# headers 包含必须的 Content-Type 和 Content-Length# datagen 是一个生成器对象,返回编码过后的参数datagen, headers = multipart_encode({"image1": open("DSC0001.jpg", "rb")})# 创建请求对象request = urllib2.Request("http://localhost:5000/upload_image", datagen, headers)# 实际执行请求并取得返回print urllib2.urlopen(request).read()Python——eventlet 绿色线程
eventlet1234try:from eventlet.green import urllib2except ImportError:import urllib212345678import urllibimport urllib2try:from gevent import monkeymonkey.patch_all()except ImportError:pass猴子补丁
属性在运行时的动态替换,叫做猴子补丁。
eventlet中大量使用了 猴子补丁,对标准函数进行绿化gevent、eventlet twisted 非阻塞网络库
基于协程的网络库gevent、eventlrequest的作者认为 eventlet 性能高于 gevent
123456789101112131415import urllibimport urllib2try:import eventleteventlet.monkey_patch()except ImportError:passif not 'eventlet' in locals():try:from gevent import monkeymonkey.patch_all()except ImportError:passurllib2 中 urlopen() 被 opener.open() 代替
123def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,cafile=None, capath=None, cadefault=False, context=None):return opener.open(url, data, timeout)git管理
三个主干- release
- devlop
- feature
feature/multiart-encode
feature/cookiejar
归纳
- core.py
def get()
123456789101112r = Request()r.method = 'GET'r.url = urlr.params = paramsr.headers = headersr.cookiejar = cookiesr.auth = _detect_auth(url, auth)r.send()return r.responseclass Request(object):
def init(self):
def setattr(self, name, value):
def _get_opener(self):opener = urllib2.build_opener(*_handlers) return opener.open
def send():
opener = self._get_opener() resp = opener(req) self._build_response(resp)
新加一个方法 就要添加一个单元测试用例
python包导入 相对导入与绝对导入
在python 2.x中启用 绝对导入
from future import absolute_import
使用tox测试代码的兼容性
tox让python 记住自己的版本
from core import version
Safer error response handling.
self.response.status_code = resp.code
self.response.status_code = getattr(resp, ‘code’, None)
request.async.get() 的实现
创建 async.py
先引入async 再import 从core 引入get
这时就可以 实现异步sync的get
–>request –>async.py –>import urllib –>monkey_patch urllib –>core.py –>get()小技巧 方便传值
12345678910111213141516def get(url, params={}, headers={}, cookies=None, auth=None):return request('GET', url, params=params, headers=headers, cookiejar=cookies,auth=_detect_auth(url, auth))def request(method, url, **kwargs):r = Request(method=method, url=url, data=data, headers=kwargs.pop('headers', {}),cookiejar=kwargs.pop('cookies', None), files=kwargs.pop('files', None),auth=_detect_auth(url, kwargs.pop('auth', None)))class Request(object):def __init__(self, url=None, headers=dict(), files=None, method=None,data=dict(), auth=None, cookiejar=None):self.url = urlself.headers = headersself.files = filesself.method = methodurllib2.urlparse 模块
(1) urlparse.urlsplit 把url 分成5部分,并返回元组>scheme >netloc >path >query >fragment url=urlparse.urlsplit('http://www.baidu.com/index.php?username=guol') SplitResult(scheme='http', netloc='www.baidu.com', path='/index.php', query='username=guol', fragment='')
(2) urlparse.urlunsplit 和urlsplit相反 生成 url
(3) urlparse.urljoin 组合生成url 确保基地址是依/ 结尾
>>> import urlparse >>> urlparse.urljoin('http://www.oschina.com/tieba','index.php') 'http://www.oschina.com/index.php' >>> urlparse.urljoin('http://www.oschina.com/tieba/','index.php') 'http://www.oschina.com/tieba/index.php'
or 操作符
In [25]: path = ‘’ or ‘/‘
In [26]: path
Out[26]: ‘/‘In [27]: path = ‘xx’ or ‘/‘
In [28]: path
Out[28]: ‘xx’@staticmethod和@classmethod的作用与区别
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
- @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
- @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
class A(object):
bar = 1
def foo(self):
print ‘foo’
@staticmethod
def static_foo():
print 'static_foo'
print A.bar
@classmethod
def class_foo(cls):
print 'class_foo'
print cls.bar
cls().foo()
A.static_foo()
A.class_foo()
class 只被初始化一次
12345678910111213141516class AuthManager(object):"""Authentication Manager."""def __new__(cls):singleton = cls.__dict__.get('__singleton__')if singleton is not None:return singletoncls.__singleton__ = singleton = object.__new__(cls)return singletondef __init__(self):self.passwd = {}self._auth = {}替换 isinstance 为 hasattr
把if isinstance(data, dict): self.data = urllib.urlencode(data) else: self.data = data
换成
if hasattr(data, 'items'):
self.data = urllib.urlencode(data)
else:
self.data = data