2

私はコードを持っています:

import gevent
import gevent.monkey; gevent.monkey.patch_all()
import requests

def func():
    try:
        requests.get('http://unavailable-host/')
    except:
        pass

def main():
    jobs = [gevent.spawn(func) for i in xrange(10)]
    gevent.joinall(jobs)

if __name__ == '__main__':
    main()

通常、このスクリプトは何も出力しません。しかし、時々 (5 回の実行のうちの 1 回で) 次のメッセージが表示されます。

Unhandled exception in thread started by
sys.excepthook is missing
lost sys.stderr

説明してください、なぜこれが起こるのか、そして正しい解決策は何ですか? また、追加すると

gevent.sleep(1)

gevent.joinall(jobs)

スクリプトは常に何も出力しません。すべて問題ありません。

4

1 に答える 1

0

編集:

これは、メイン プログラムが既に終了した後にスレッドが処理を実行しようとしている (stdout/stderr への出力など) ことに関係しているようです。

Python Bugs: issue1722344を参照してください。

同様のSOの質問に対するこの回答のMartijn Pietersのコメント:

実際、python が終了していて、まだアクティブなスレッドがあるため、エラーが生成されます。

以前の(そして完全に間違った)答え:

あなたが経験しているのは、 のあまり面白くない副作用の 1 つですmonkey_patch

requestssocketインターネットを介して特定のアドレスにデータを転送するための基本的なメカニズムとして使用します。gevent.monkey.patch_all()stdlibsocketgevent.socket、非同期 (非ブロッキング) ソケットである に置き換えます。そのため、コード内のどこか深いところで (私の推測では、http.clientによって使用されurllib、次に によって使用されますrequests)、sock.recv(X)コマンドが作成されます。コードは、X バイトが受信されるか、ソケットが閉じられるまでブロックされると予想されます。代わりに、ソケットが に置き換えられているため、現在ストリーム バッファーにあるバイト数だけをすぐに返すgevent.socketため、コードが壊れます。

ただし、あなたの場合の簡単な解決策は、単にgeventを使用するように構築されたリクエストである grequests を使用することです (実際には、独自の monkey_patch を実行します)。

于 2013-03-20T19:36:57.887 に答える