13

最近、os.fork()を実行して 2 つのプロセスに分割するスクリプトを作成する必要がありました。子プロセスはサーバー プロセスになり、os.pipe()で作成されたパイプを使用して親プロセスにデータを返します。通常どおり、子が'r'パイプの端を閉じ、親がパイプの端を閉じます。'w'pipe() からの戻り値をos.fdopenでファイル オブジェクトに変換します。

私が抱えている問題は次のとおりです。プロセスが正常に分岐し、子がサーバーになります。'w'すべてがうまく機能し、子供はパイプの開いた端にデータを忠実に書き込みます。残念ながら、パイプの親エンドは 2 つの奇妙なことを行います: A) パイプのエンドでの操作を
ブロックします。次に、パイプの端が完全に閉じ られていない限り、パイプに置かれたデータを読み取ることができません。read()'r'
'w'

私はすぐにバッファリングが問題であると考え、pipe.flush()呼び出しを追加しましたが、これらは役に立ちませんでした。

書き込み終了が完全に閉じられるまでデータが表示されない理由を誰かが明らかにすることはできますか? read()そして、呼び出しをブロックしないようにする戦略はありますか?

これは、パイプを分岐または使用した初めての Python プログラムなので、単純な間違いを犯した場合はご容赦ください。

4

4 に答える 4

13

サイズを指定せずに read() を使用していますか、またはパイプをイテレータ ( for line in f) として扱っていますか? もしそうなら、それがおそらく問題の原因です - read() は、読み取り可能なものを単に読み取るのではなく、ファイルの最後まで読み取るように定義されています。これは、子が close() を呼び出すまでブロックすることを意味します。

リンク先のコード例では、これで問題ありません。親はブロックするように動作しており、分離目的で子を使用しているだけです。続行したい場合は、投稿したコードのように非ブロッキング IO を使用するか (ただし、半分完全なデータを処理する準備をしてください)、チャンクで読み取ります (例: r.read(size) または r.readline() ) 特定のサイズ/行が読み取られるまでのみブロックします。(まだ子でフラッシュを呼び出す必要があります)

パイプをイテレータとして扱っているように見えますが、さらにバッファも使用してfor line in r:います。各行をすぐに消費する必要がある場合、 " " が必要なものを提供しない可能性があるからです。これを無効にすることは可能かもしれませんが、fdopen でバッファー サイズに 0 を指定するだけでは十分ではないようです。

動作するはずのサンプルコードを次に示します。

import os, sys, time

r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)

pid = os.fork()
if pid:          # Parent
    w.close()
    while 1:
        data=r.readline()
        if not data: break
        print "parent read: " + data.strip()
else:           # Child
    r.close()
    for i in range(10):
        print >>w, "line %s" % i
        w.flush()
        time.sleep(1)
于 2009-05-16T15:30:19.490 に答える
6

使用する

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

read()を呼び出す前に、両方の問題を解決しました。read()呼び出しはブロックされなくなり、書き込み終了時のflush()の後にデータが表示されます。

于 2009-05-16T02:14:38.577 に答える
5

I/O のブロックとバッファリングの問題は解決したようです。

別のアプローチを試すことにした場合の注意: subprocess は fork/exec イディオムと同等/代替です。それはあなたがしていることではないようです: フォーク (exec ではない) と 2 つのプロセス間でデータを交換するだけです。この場合、multiprocessingモジュール (Python 2.6+) の方が適しています。

于 2009-05-16T02:56:06.683 に答える
-10

Pythonアプリケーションのフォークの「親」と「子」の部分はばかげています。これは、16ビットUNIX時代からの遺産です。これは、fork/execとexecが小さな小さなプロセッサを最大限に活用するための重要なことだった日からの愛情です。

Pythonコードを親と子の2つの部分に分割します。

親パーツは、子パーツを実行する ためにサブプロセスを使用する必要があります。

フォークとエグゼクティブはどこかで発生する可能性がありますが、気にする必要はありません。

于 2009-05-16T02:05:01.860 に答える