web-dev-qa-db-ja.com

multiprocessing.Queueでのパイプエラーの破損

Python2.7では、multiprocessing.Queueは、関数内から初期化されると、壊れたエラーをスローします。私は問題を再現する最小限の例を提供しています。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import multiprocessing

def main():
    q = multiprocessing.Queue()
    for i in range(10):
        q.put(i)

if __name__ == "__main__":
    main()

以下の壊れたパイプエラーをスローします

Traceback (most recent call last):
File "/usr/lib64/python2.7/multiprocessing/queues.py", line 268, in _feed
send(obj)
IOError: [Errno 32] Broken pipe

Process finished with exit code 0

理由がわからない。関数内からQueueオブジェクトを生成できないのは確かに奇妙です。

11
hAcKnRoCk

ここで何が起こるかは、main()を呼び出すと、Queueが作成され、その中に10個のオブジェクトが配置されて関数が終了し、Queueを含む内部の変数とオブジェクトがすべてガベージコレクションされます。しかし、Queueの最後の数値を送信しようとしているため、このエラーが発生します。

ドキュメントから documentation

「プロセスが最初にアイテムをキューに入れると、オブジェクトをバッファーからパイプに転送するフィーダースレッドが開始されます。」

put()は別のスレッドで作成されるため、スクリプトの実行をブロックせず、キュー操作を完了する前にmain()関数を終了できます。

これを試して :

#!/usr/bin/python
# -*- coding: utf-8 -*-

import multiprocessing
import time
def main():
    q = multiprocessing.Queue()
    for i in range(10):
        print i
        q.put(i)
    time.sleep(0.1) # Just enough to let the Queue finish

if __name__ == "__main__":
    main()

オブジェクトがjoinに配置されるまで、キューまたはブロックの実行をQueueする方法が必要です。ドキュメントを参照してください。

9
CoMartel

Queue.put()を起動すると、暗黙的なスレッドが開始され、データがキューに配信されます。その間、メインアプリケーションは終了し、データの終了ステーションはありません(キューオブジェクトはガベージコレクションされます)。

私はこれを試します:

_from multiprocessing import Queue

def main():
    q = Queue()
    for i in range(10):
        print i
        q.put(i)
    q.close()
    q.join_thread()

if __name__ == "__main__":
    main()
_

join_thread()は、バッファ内のすべてのデータが確実にフラッシュされるようにします。 close()join_thread()の前に呼び出す必要があります

15
Peter Svac

@HarryPotFleurによって提案されているtime.sleep(0.1)を使用した遅延により、この問題は解決されました。しかし、私はpython3でコードをテストしましたが、壊れたパイプの問題はpython3ではまったく発生しません。これはバグとして報告され、後で修正されたと思います。

0
hAcKnRoCk