13

multiprocessing.Queue.getを使用すると、EINTRが原因で例外が発生することがあります。

時々これが正当な理由なしに起こることを私は確かに知っています(私はtmux buffrで別のペインを開きます)、そしてそのような場合、私は作業を続けて操作を再試行したいと思います。

他の場合には、エラーは正当な理由によるものであり、実行を停止するか、エラーを修正する必要があると想像できます。

どうすれば2つを区別できますか?

前もって感謝します

4

2 に答える 2

17

アプリケーションが他のEINTR入力を待機している間にシグナルを受信すると、多くのシステム コールからエラーが返される可能性があります。通常、これらのシグナルは非常に無害であり、Python によって既に処理されていますが、基礎となるシステム コールは中断されてしまいます。C/C++ コーディングを行う場合、これが のような関数に完全に依存できない理由の 1 つですsleep()。Python ライブラリは、このエラー コードを内部で処理することがありますが、明らかにこの場合はそうではありません。

この問題について議論しているこのスレッドを読むことに興味があるかもしれません。

一般的なアプローチは、単純にエラーを処理し、操作を再試行することです。これは、キューEINTRのメソッドを安全に処理できるはずです。get()このようなものを使用して、キューをパラメーターとして渡し、キューでのget()メソッドの使用を置き換えることができます。

import errno

def my_queue_get(queue, block=True, timeout=None):
    while True:
        try:
            return queue.get(block, timeout)
        except IOError, e:
            if e.errno != errno.EINTR:
                raise

# Now replace instances of queue.get() with my_queue_get(queue), with other
# parameters passed as usual.

特定のシグナルEINTR(たとえばSIGHUP旗を拾う。この場合、ループから抜け出し、受信した場合はシグナル フラグをチェックする必要があるかもしれませんEINTR

ただし、シグナル処理を使用していない場合は、操作を無視して繰り返すことができるはずEINTRです。Python 自体がシグナルを処理する必要がある場合は、シグナル ハンドラーで既に処理されているはずです。

于 2013-01-10T16:08:05.743 に答える
8

古い質問、最新の解決策: Python 3.5 の時点で、素晴らしいPEP 475 - EINTR で失敗するシステム呼び出しの再試行が実装され、問題が解決されました。要約は次のとおりです。

標準ライブラリで提供されるシステム コール ラッパーは、EINTRアプリケーション コードが負担から解放されるように、 で失敗した場合に自動的に再試行する必要があります。

システム コールとは、I/O またはその他のシステム リソースの処理に関連する標準 C ライブラリによって公開される関数を意味します。

基本的に、システムは失敗したコードをキャッチして再試行するEINTRので、それを処理する必要はありません。古いリリースをターゲットにしている場合は、while Trueループを使用することをお勧めします。ただし、Python 3.3 または 3.4 を使用している場合は、をキャッチしてチェックするInterruptedError代わりに、専用の例外をキャッチできることに注意してください。IOErrorEINTR

于 2015-04-02T11:07:08.393 に答える