http request with timeout, maximum size and connection pooling
我正在寻找一种在Python(2.7)中执行HTTP请求的方法,其中有3个要求:
- 超时(为了可靠性)
- 内容最大大小(用于安全)
- 连接池(用于性能)
我已经检查了相当多的PythonHTTP库,但它们都不满足我的要求。例如:
很好,但不合用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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) |
请求:无最大大小
1 2 3 4 5 6 7 | 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:从来没有"read"方法起作用,即使有一个50mo的文件……
httplib:httplib.httpConnection不是池(只有一个连接)
我简直不敢相信URLLIB2是我能使用的最好的HTTP库!所以如果有人知道天秤座可以做什么,或者如何使用以前的天秤座…
编辑:
我找到的最好的解决方案要归功于Martijn Pieters(即使对于大文件,str加法也不会减慢速度)。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() |
您可以使用
1 2 3 4 5 6 7 8 | 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) |
或者,您可以在读取之前在
1 2 3 4 5 6 7 8 9 | 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) |
如果您不喜欢使用这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
这里处理压缩数据大小的方式有细微的差别;
这两种方法都不允许