なぜ最後の利回り壊れ出力以外の成分をパイプラインに()で通信を呼び出すことができますか?

Mwuck:

私は、大規模な.fastqファイル(59百万行)で約500パターンの発生をカウントします。パターンは、長いすべて正確に20文字です。

UNIXでは、これは簡単なようになります:

grep -F -o -f patterns.txt big_file.fastq | sort | uniq -c

しかし、私はPythonのサブプロセスのライブラリを使用してパイプを作成しましたので、一時的なパターンファイルを書き込ん避けたいです。

from subprocess import Popen, PIPE, STDOUT

p1 = Popen(["grep", "-F", "-o", "-f", "-", "big_file.fastq"], shell = False, stdin = PIPE, stdout = PIPE, stderr= STDOUT)
p2 = Popen(["sort"], shell = False, stdin = p1.stdout, stdout = PIPE, stderr = STDOUT)
p3 = Popen(["uniq", "-c"], shell = False, stdin = p2.stdout, stdout = PIPE, stderr = STDOUT)

私は、コールコードさio.StringIOファイルのような入力のようなオブジェクトを提供、これに)(通信(私が使用してgrepコマンドに渡されます「 - 」):

import io

patterns_file = io.StringIO("\n".join(patterns_list))
p3.communicate(input = patterns_file.read().encode('utf-8'))[0]

私はこのようなuniqの上()で通信を呼び出すときに、これはうまく動作します。

しかし、テスト中に私が誤ってパイプの最初の部分にそれを呼びました。

p1.communicate(input = patterns_file.read().encode('utf-8'))[0]

これは、20個の文字を予想より短いか長いだった試合を含め、私は完全に間違って出力を与えました。

これは、なぜ私は理解していません。唯一のパイプの一部が関与し、残りを無視P1上)(通信呼び出していないでしょうか?正しくはgrepするP2とP3原因P1を削除します。私はpopenのがどのように機能するかについて何かをしないのです感じます。

すべてのヘルプは大歓迎です。

チャールズダフィー:

あなたがインスタンス化するとPopen、オブジェクトを、サブプロセスは、彼らはすぐに開始されている参照してください。したがって、あなただけ呼び出す場合でもcommunicate()上のp1p2そしてp3また、実行されています。

なぜこれが重要ですか?のでp2、まだFIFOにそのSTDINを添付していたにp1その出力を書いています!

場合sortの操作はp2まだあなたが直接その同じ内容を読み取るために、あなたのPythonプログラムを尋ねると同時に、内容を読んでいる、あなたが終わるp1それらの間で分割の出力。はしゃぎは、結果として起きることが予想されます。両方の場合にのみ、p2およびcommunicate()20バイトの倍数だったが、確実に記録境界に分裂が起きだろうとブロックを読み取り、バッファリングされていないために読み込みに使用される典型的なチャンクサイズは4096の倍数である。ました


ところで-のための多くの FIFOが比較的小さいバッファを持っているので、これは、重大な影響として持っていないプログラム。それは非常に迅速に出力を遮断してしまうでしょう、したがって、その出力は、少なくとも部分的にフラッシュされるまで、さらに入力を読んで停止する読み込み入力の各行の出力のラインを書き込むプログラム。sortそれは、出力の最初の行がどうなるかを知っている前に、それはすべての入力を読み込む必要があるため、例外です!

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=398962&siteId=1