从另一个线程关闭“Python请求”连接

时间:2013-05-05 23:37:05

标签: python python-requests

要尽快关闭应用程序,我是否可以中断来自另一个线程的requests.post调用并立即终止连接?

我玩过适配器,但到目前为止没有运气:

for ad in self.client.session.adapters.values():
    ad.close()

3 个答案:

答案 0 :(得分:4)

正确的方法是使用消息传递到另一个线程。我们可以通过使用共享的全局变量来做一个穷人版本。例如,您可以尝试运行此脚本:

#!/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保护的情况下,您将需要在消息传递状态周围使用更加谨慎,以避免出现多线程错误。我把它留给了实现者。

答案 1 :(得分:2)

我找到了一种方法,这里是如何中断连接

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

答案 2 :(得分:0)

因此,如果您从交互式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.

所以从本质上讲,你会发现你不能影响尚未完成的连接。