Python requests, how to limit received size, transfer rate, and/or total time?
我的服务器执行外部请求,我希望限制失败请求所能造成的损害。我希望在以下情况下取消请求:
- 请求的总时间超过了某个限制(即使数据仍在到达)
- 接收的总大小超过了某些限制(我需要在接受更多数据之前取消)
- 传输速度下降到某个水平以下(尽管如果可以提供总的时间限制,我可以不使用这个速度)
注意,我不会在请求中查找timeout参数,因为这只是不活动的超时。我找不到任何与总超时或限制总大小的方法有关的信息。一个例子显示了HTTPAdapter上的maxsize参数,但没有记录。
我如何使用requests来实现这些需求?
- 我认为,maxsize是连接池的限制,而不是接收到的大小。
- 不是一个解决方案,但是您还应该确保大小限制也考虑到头的大小,而有些库(如urllib)不考虑头的大小。
- @瓦伦蒂诺伦茨,是的,的确,我希望标题的大小限制比内容小得多。
- 关于总超时,您可能想看看我对类似问题的回答:stackoverflow.com/a/22377499/1653521
您可以尝试设置stream=True,然后在读取数据时超过时间或大小限制时中止请求。
从requests2.3.0版开始,超时也适用于流式请求,因此您所需要做的就是为初始连接和每个迭代步骤留出一个超时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| r = requests.get(..., stream=True, timeout=initial_timeout)
r.raise_for_status()
if int(r.headers.get('Content-Length')) > your_maximum:
raise ValueError('response too large')
size = 0
start = time.time()
for chunk in r.iter_content(1024):
if time.time() - start > receive_timeout:
raise ValueError('timeout reached')
size += len(chunk)
if size > your_maximum:
raise ValueError('response too large')
# do something with chunk |
根据需要调整超时。
对于requests版本<2.3.0(包括此更改),您无法超时r.iter_content()的产量;在块中间停止响应的服务器仍将绑定连接。您必须将上述代码包装在一个额外的超时函数中,以便尽早切断长时间运行的响应。
- 因为我已经在使用eventlet,所以我可能只需要将整个块包装在一个eventlet.timeout.Timeout中。但我仍然需要流媒体的大小限制。
- @EDA-QAMORT-ORA-Y:没错,使用本地的eventlet功能将胜过我链接到这里的超时。
- 这种方法似乎有一个重大问题:iter_content没有超时。github.com/kennethreitz/requests/issues/1948年
- @EDA-QAMORT-ORA-Y:我在回答中如此明确地陈述:这不会阻止对您的延迟响应(在块中间停止响应),这就是为什么您希望用特定的每函数超时包装它。
- 一个小建议是在每个块到达时增加接收到的内容,就像在另一个答案中那样。+ 1
- @ZX81:这就是块注释的作用所在;您不必将所有内容收集到一个大字符串中,也可以迭代地处理它。
- @是的,我看到了。这只是一个建议,让代码对普通过路人更立即有用。不过不用担心,他们可以阅读评论。最美好的祝愿