7

このトピックに関するいくつかの質問を読んで、子プロセスが親プロセスからファイル記述子を継承することを理解しました。これにより、親が接続を閉じたときに子が EOFError を受け取ることがより困難になります。

しかし、私の状況は逆で、直面している問題がわかりません。

子プロセスを開始する親プロセスがあり、作成したパイプ接続の一方の端にアクセスできるようにします。子プロセスが完了したり、誤動作したりすると、すべてが停止し、接続が閉じられます。この時点で、子プロセスは機能していないことがわかります。

次に、親プロセスの接続がブロッキング recv 呼び出しで EOFError をスローすることを期待しています。しかし、代わりにただそこに座って待っています。

ここで何が欠けていますか?

編集

この例は問題を表していると思います:

from multiprocessing import Process, Pipe
from threading import Thread
import time

class Parent(object):

    def __init__(self):
        self.parent_conn, child_conn = Pipe()
        self.child = Process(target=Child, args=(child_conn,))
        self.child.start()        

        def recv():
            try:
                self.parent_conn.recv()
            except EOFError:
                print "EOF"
            except:
                print "something else"

        # Does not work
        recv()

        # Works fine
        t = Thread(target=recv)
        t.setDaemon(True)
        t.start()

    def close(self):
        self.parent_conn.close()
        self.child.join()

class Child(object):

    def __init__(self, conn):
        conn.close()

if __name__ == "__main__":
    p = Parent()
    time.sleep(1)
    p.close()

別のスレッドを使用すると、親は独自の接続を閉じることができ、すべてが正常に機能します。(これを行うには、子が終了したことを何らかの方法で知る必要があることに注意してください)代わりに、recv を直接呼び出すと、明らかにブロックされますが、子プロセスが接続を閉じるとすぐに EOFError が発生すると思われます。しかし、そうではありません。誰でも明確にできますか?

4

1 に答える 1

8

child_conn.close()の後に追加しself.child.start()ます。未使用の端を閉じるためにパイプを操作するのは慣用的です。また、(オプションで)duplex=Falseパラメータを指定します。

事は、すぐに閉まるかどうかは事前にわかりません.. 通常、子供は送受信できるはずです。さらに、なぜこれがうまくいかないのか、まだわかりません。

  1. child_conn.close()では、がすぐに終了する必要があるという意味ではありません
  2. parent_conn.recv誰かが戻ってくる可能性がある限り、戻ってこないchild_conn.send(). child_connが(子または親で)開かれている場合、可能性があります

別のスレッドを使用すると、親は独自の接続を閉じることができ、すべてが正常に機能します。これを行うには、子供が終わったことを何とか知る必要があることに注意してください

あなたはそれを知る必要はありません。子で接続が開かれるとすぐに閉じることができます。child_conn.close()後で親を呼び出すことは、self.child.start()子供が何をしても問題ありません。

デュプレックスオプションについてももう少し説明していただけますか?

duplex=Falseは、パイプが一方向であることを意味します。つまり、parent_conn.recv()andのみを呼び出すことができますchild_conn.send()。それ以外の場合は双方向であり、両方の接続が送信/受信をサポートします。

于 2013-12-17T09:18:59.050 に答える