7

アプリケーションをできるだけ早く閉じるには、別のスレッドからの requests.post 呼び出しを中断して、接続をすぐに終了させることはできますか?

私はアダプターで遊んだが、今のところうまくいかない:

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

3 に答える 3

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 の保護を受けていない場合は、厄介なマルチスレッドのバグを避けるために、メッセージの受け渡し状態にもっと注意を払う必要があります。私はそれを実装者に任せています。

于 2013-05-07T17:41:40.190 に答える
0

そのため、インタラクティブ シェルから次の操作を行うと、アダプターを閉じても目的の動作が行われないことがわかります。

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 を呼び出すclearと、基になる urrllib3 PoolManager が呼び出されます。そのメソッドの urllib3 のドキュメントから、次のことがわかります。

This will not affect in-flight connections, but they will not be
re-used after completion.

したがって、本質的に、まだ完了していない接続に影響を与えることはできないことがわかります。

于 2013-05-06T14:10:21.933 に答える