3

Python でサブプロセスとして呼び出す必要があるプログラムがあります。プログラムはJavaで書かれています。ええ、私は知っています...

とにかく、上記のプログラムからのすべての出力をキャプチャする必要があります。

残念ながら、subprocess.popen2 または subprocess.Popen を communicate[0] で呼び出すと、stdout に割り当てられた subprocess.PIPE を使用している場合と、ファイル記述子を使用している場合に、出力データの約 10% が失われます。 (open からの戻り) stdout に割り当てられます。

subprocess のドキュメントは、子プロセスからのすべての出力をキャプチャしようとしている場合、 subprocess.PIPE の使用が揮発性であることを明確に示しています。

私は現在 pexpect を使用して出力を tmp ファイルにダンプしていますが、明らかな理由で永遠に時間がかかります。

ディスクへの書き込みを避けるために、すべてのデータをメモリに保持したいと思います。

どんなお勧めも大歓迎です!ありがとう!

import subprocess

cmd = 'java -Xmx2048m -cp "/home/usr/javalibs/class:/home/usr/javalibs/libs/dependency.jar" --data data --input input" 

# doesn't get all the data
#
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

OR
# doesn't get all the data
#
fd = open("outputfile",'w')
p = subprocess.Popen(cmd, stdout=fd, shell=True)
p.communicate()
fd.close() # tried to use fd.flush() too.

# also tried
# p.wait() instead of p.communicate(), but wait doesn't really wait for the java program to finish running - it doesn't block

OR
# also fails to get all the data
#
import popen2
(rstdout, rstdin) = popen2.popen2(cmd)

予期される出力は、一連の ASCII 行 (数千行) です。行には数字と行末文字が含まれています

0\n
1\n
4\n
0\n
...
4

2 に答える 2

2

私はsubprocessはるかに大きな出力で使用していましstdoutたが、そのような問題は見られませんでした。あなたが示したものから根本的な原因を結論付けるのは難しいです。私は以下をチェックします:

p.wait()あなたのために働いていなかったので。PIPEJavaプログラムを読んでいるときに、最後の10%を印刷するのにまだ忙しい場合があります。p.wait()最初にまっすぐになります:

  • を読む前に十分な長さの待機時間(たとえば30秒)を挿入PIPEします。10%が表示されますか?
  • p.wait()それがあなたのJavaプログラムをブロックしないのは疑わしいです。あなたのJavaプログラムは他のプログラムをさらにサブプロセッシングしていますか?
  • の戻り値を確認してくださいp.wait()。Javaプログラムは正常に終了しましたか?

問題が並行性モデルにない場合は、Javaプログラムで正しく印刷されているかどうかを確認してください。

  • 印刷先としてJavaプログラムで使用した関数は何stdoutですか?それは傾向がありますか、それとも無視しIOExceptionますか?
  • ストリームを正しくフラッシュしましたか?最後の10%は、Javaプログラムの終了時に適切にフラッシュせずにバッファーにある可能性があります。
于 2012-05-21T18:29:10.927 に答える
2

実際に呼び出しているプロセスに関連するものでなければなりません。行をエコーアウトする別の python スクリプトで簡単なテストを行うことで、これを確認できます。

out.py

import sys

for i in xrange(5000):
    print "%d\n" % i

sys.exit(0)

test.py

import subprocess

cmd = "python out.py"
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

print output

したがって、問題はデータのサイズではなく、呼び出しているプロセスとの通信であることを確認できます。

Popenの内部バッファに関する過去の問題について読んだことがあるので、実行しているpythonのバージョンも確認する必要があります(ただし、通常はそれを修正することを提案したように、別のファイルハンドルを使用します)。

サブプロセス呼び出しが無期限にハングしていた場合、バッファの問題になります。しかし、行が足りないだけでプロセスが完了している場合、Popen はその役割を果たしています。

于 2012-05-21T19:06:17.853 に答える