Python Popen、ストリームと複数のプロセスを閉じる
質問
gzip、uuencode、および標準出力に出力したいデータがあります。私が基本的に持っているのは:
compressor = Popen("gzip", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
encoder = Popen(["uuencode", "dummy"], stdin = compressor.stdout)
データをコンプレッサーに供給する方法は、compiler.stdin.write(stuff)を使用することです。
実際に行う必要があるのは、コンプレッサーにEOFを送信することであり、その方法はわかりません。
ある時点で、compressor.stdin.close()を試しましたが、うまくいきません-コンプレッサーがファイルに直接書き込む場合はうまくいきますが、上記の場合、プロセスは終了せず、停止しますcompress.wait()で。
提案?この場合、gzipは例であり、1つのプロセスの出力を別のプロセスにパイプすることで実際に何かをする必要があります。
注:圧縮する必要のあるデータはメモリに収まらないため、ここでは通信はあまり良い選択肢ではありません。また、実行した場合
compressor.communicate("Testing")
上記の2行の後、それでもエラーでハングします
File "/usr/lib/python2.4/subprocess.py", line 1041, in communicate rlist, wlist, xlist = select.select(read_set, write_set, [])
解決
問題は、パイプを開く順序に関係していると思われます。 UUEncodeの面白いところは、適切な方法で着信パイプがない場合に起動するときに鳴るということです(stopenおよびstdoutとしてPIPEのみを使用して爆発を確認するには、Popen呼び出しでそれ自体で起動します)
これを試してください:
encoder = Popen(["uuencode", "dummy"], stdin=PIPE, stdout=PIPE)
compressor = Popen("gzip", stdin=PIPE, stdout=encoder.stdin)
compressor.communicate("UUencode me please")
encoded_text = encoder.communicate()[0]
print encoded_text
begin 644 dummy
F'XL(`%]^L$D``PL-3<U+SD])5<A-52C(24TL3@4`;2O+"!(`````
`
end
あなたは正しい、ところで...汎用EOFをパイプに送信する方法はありません。結局のところ、各プログラムは実際に独自のEOFを定義しています。それを行う方法は、あなたがやろうとしていたように、パイプを閉じることです。
編集:uuencodeについてもっと明確にすべきです。シェルプログラムとしてのデフォルトの動作は、コンソール入力を期待することです。 &quot; live&quot;なしで実行する場合着信パイプ、コンソール入力の待機をブロックします。素材をコンプレッサーパイプに送る前に2番目にエンコーダーを開くと、エンコーダーは入力を開始するのを待ってブロックしていました。ジェルブは、何かがブロックされているという点で正しかった。
他のヒント
これは、Pythonで直接行うべきではありません。シェルを使用してこれを行う方がはるかに優れたアイデアとなるように、その動作方法に偏りがあります。 subprocess.Popen(&quot; foo | bar&quot ;, shell = True)を使用できる場合は、すべての方が優れています。
何が起こっているのかと言えば、gzipは入力のすべてをまだ出力できず、stdoutの書き込みが完了するまでプロセスは終了しません。
straceを使用すると、プロセスがブロックしているシステム呼び出しを確認できます。 ps auxwf
を使用してgzipプロセスであるプロセスを見つけ、次に strace -p $ pidnum
を使用して、実行しているシステムコールを確認します。 stdinはFD 0であり、stdoutはFD 1であることに注意してください。これらのファイル記述子で読み取りまたは書き込みが行われる可能性があります。
圧縮するだけでファイルラッパーが不要な場合は、zlibモジュールの使用を検討してください
import zlib
compressed = zlib.compress("text")
shell = TrueおよびUNIXパイプの提案が機能しない理由は何ですか?
from subprocess import *
pipes = Popen("gzip | uuencode dummy", stdin=PIPE, stdout=PIPE, shell=True)
for i in range(1, 100):
pipes.stdin.write("some data")
pipes.stdin.close()
print pipes.stdout.read()
動作しているようです