我正在寻找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库!所以如果有人知道librairy可以做什么,或者如何使用之前的librairy ......
修改
我发现感谢Martijn Pieters的最佳解决方案(即使对于巨大的文件,StringIO也不会减速,其中str添加很多)。
r = requests.get('https://github.com/timeline.json', stream=True)
size = 0
ctt = StringIO()
for chunk in r.iter_content(2048):
size += len(chunk)
ctt.write(chunk)
if size > maxsize:
r.close()
raise ValueError('Response too large')
content = ctt.getvalue()
答案 0 :(得分:13)
你可以用requests
做到这一点;但你需要知道raw
对象是urllib3
胆量的一部分,并利用HTTPResponse.read()
call支持的额外参数,这可以指定你想要读取解码数据:
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()
generator version:
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()
调用已经允许您访问相关内容,因此确实没有必要。