我正在寻找一种在 Python (2.7) 中执行具有 3 个要求的 HTTP 请求的方法:
我已经检查了几乎所有的Python HTTP库,但没有一个满足我的要求。例如:
urllib2:很好,但没有池化
import urllib2
import json
r = urllib2.urlopen('https://github.com/timeline.json', timeout=5)
content = r.read(100+1)
if len(content) > 100:
print 'too large'
r.close()
else:
print json.loads(content)
r = urllib2.urlopen('https://github.com/timeline.json', timeout=5)
content = r.read(100000+1)
if len(content) > 100000:
print 'too large'
r.close()
else:
print json.loads(content)
请求:无最大尺寸
import requests
r = requests.get('https://github.com/timeline.json', timeout=5, stream=True)
r.headers['content-length'] # does not exists for this request, and not safe
content = r.raw.read(100000+1)
print content # ARF this is gzipped, so not the real size
print json.loads(content) # content is gzipped so pretty useless
print r.json() # Does not work anymore since raw.read was used
urllib3:即使使用 50Mo 文件,“读取”方法也无法正常工作...
httplib:httplib.HTTPConnection 不是一个池(只有一个连接)
我简直不敢相信 urllib2 是我能使用的最好的 HTTP 库!因此,如果有人知道什么库可以做到这一点或如何使用以前的库之一......
用
requests
就可以了;但您需要知道 raw
对象是 urllib3
核心的一部分,并利用 HTTPResponse.read()
调用 支持的额外参数,这可以让您指定要读取 decoded 数据:
import requests
r = requests.get('https://github.com/timeline.json', timeout=5, stream=True)
content = r.raw.read(100000+1, decode_content=True)
if len(content) > 100000:
raise ValueError('Too large a response')
print content
print json.loads(content)
或者,您可以在读取之前在
decode_content
对象上设置 raw
标志:
import requests
r = requests.get('https://github.com/timeline.json', timeout=5, stream=True)
r.raw.decode_content = True
content = r.raw.read(100000+1)
if len(content) > 100000:
raise ValueError('Too large a response')
print content
print json.loads(content)
如果您不喜欢像这样深入了解
urllib3
的内容,请使用 response.iter_content()
分块迭代解码的内容;这也使用底层 HTTPResponse
(使用 .stream()
生成器版本:
import requests
r = requests.get('https://github.com/timeline.json', timeout=5, stream=True)
maxsize = 100000
content = ''
for chunk in r.iter_content(2048):
content += chunk
if len(content) > maxsize:
r.close()
raise ValueError('Response too large')
print content
print json.loads(content)
此处处理压缩数据大小的方式存在细微差别;
r.raw.read(100000+1)
只能读取 100k 字节的压缩数据;未压缩的数据将根据您的最大大小进行测试。 iter_content()
方法将读取更多未压缩数据在极少数情况下,压缩流比未压缩数据更大。
这两种方法都不允许 r.json()
起作用;
response._content
属性不是由这些设置的;当然,您可以手动执行此操作。但由于
.raw.read()
和
.iter_content()
调用已经让您可以访问相关内容,因此实际上没有必要。