要尽快关闭应用程序,我可以中断来自另一个线程的requests.post调用并立即终止连接吗?从另一个线程关闭“Python请求”连接
我打适配器,但至今没有运气:
for ad in self.client.session.adapters.values():
ad.close()
要尽快关闭应用程序,我可以中断来自另一个线程的requests.post调用并立即终止连接吗?从另一个线程关闭“Python请求”连接
我打适配器,但至今没有运气:
for ad in self.client.session.adapters.values():
ad.close()
因此,如果您从交互shell下,你会看到在关闭适配器似乎没有做什么你”重新寻找。
import requests
s = requests.session()
s.close()
s.get('http://httpbin.org/get')
<Response [200]>
for _, adapter in s.adapters.items():
adapter.close()
s.get('http://httpbin.org/get')
<Response [200]>
s.get('https://httpbin.org/get')
<Response [200]>
这看起来可能是在请求中的错误,但在一般情况下,关闭适配器应该阻止你提出更多要求,但我不能完全肯定它会中断目前运行的请求。
查看HTTPAdapter(同时为标准'http://'
和'https://'
适配器供电),调用close将调用底层urrllib3 PoolManager上的clear
。从这个方法的urllib3的文档,你看到了:
This will not affect in-flight connections, but they will not be
re-used after completion.
所以在本质上,你看,你无法影响尚未完成的连接。
我找到了一种方法,在这里是如何中断连接
def close():
time.sleep(5)
r.raw._fp.close()
t = threading.Thread(target=close).start()
print "getting"
s = requests.Session()
r = s.get("http://download.thinkbroadband.com/1GB.zip", stream = True)
for line in r.iter_content(1024):
log.debug("got it: %s", len(line))
print "done"
但是这是一个黑客,我不喜欢它,私有成员可以,我回国的urllib2
改变未来正确的做法是将消息传递到另一个线程。我们可以通过使用一个共享的全局变量来做一个糟糕的版本。举个例子,你可以尝试运行此脚本:
#!/usr/bin/env python
# A test script to verify that you can abort streaming downloads of large
# files.
import threading
import time
import requests
stop_download = False
def download(url):
r = requests.get(url, stream=True)
data = ''
content_gen = r.iter_content()
while (stop_download == False):
try:
data = r.iter_content(1024)
except StopIteration:
break
if (stop_download == True):
print 'Killed from other thread!'
r.close()
if __name__ == '__main__':
t = threading.Thread(target=download,
args=('http://ftp.freebsd.org/pub/FreeBSD/ISO-IMAGES-amd64/9.1/FreeBSD-9.1-RELEASE-amd64-dvd1.iso',)
).start()
time.sleep(5)
stop_download = True
time.sleep(5) # Just to make sure you believe that the message actually stopped the other thread.
当生产这样做,特别是如果你没有GIL的保护,你会希望使用更谨慎周围的消息传递状态以避免尴尬的多线程错误。我要把它留给实现者。
此外,您可以使用非常小的内容大小来取得更好的控制权。而你的'content_gen = r.iter_content()'是不必要的;} – 2013-05-08 13:34:23
'iter_content()'返回一个迭代器(或者生成器),所以你应该像'content_gen = r.iter_content(1024)'' '下(content_gen)'。 – 2013-10-09 05:12:08
@Lukasa,你能告诉我,当'r = requests.get(url,stream = True)'行被执行时,响应数据是否会全部下载到ram的某处?因为我不确定何时'data = r.iter_content(1024)',1024字节的数据来自哪里。我想知道如果是这样的话,以后终止请求是没有用的,因为数据已经被下载(请求/响应结束)。 – Bin 2015-11-11 09:22:52
是的,不幸的是请求不是这样设计的,我想小的http请求是主要目的。我使用它作为桌面应用程序,客户端必须让其中断。 – 2013-05-07 04:51:35
您可能会深入挖掘urllib3并强行关闭套接字,但urllib3位于httplib之上,我不知道这是否可能。如果你想要细粒度的控制,你可以使用原始套接字自己构造整个请求(并解析响应)。当用户想要取消某件事情时,只需关闭套接字即可。虽然这是很多工作。 – 2013-05-07 13:26:40