1

サブプロセス モジュールを使用して python スクリプトをサブプロセスとして実行して遊んでいましたが、出力を 1 行ずつ読み取る際に問題が発生しました。

私が読んだドキュメントは、サブプロセスを使用して stdout で readline() を呼び出すことができる必要があることを示しています。呼び出しているスクリプトが bash スクリプトである場合、これは実際に機能します。ただし、Python スクリプト readline() を実行すると、スクリプト全体が完了するまでブロックされます。

問題を繰り返すいくつかのテスト スクリプトを作成しました。テスト スクリプトでは、python スクリプト (tst.py) 内からサブプロセスとして python スクリプト (tst1.py) を実行し、tst1.py の出力を 1 行ずつ読み取ります。

tst.py は tst1.py を開始し、出力を 1 行ずつ読み取ろうとします。

#!/usr/bin/env python
import sys, subprocess, multiprocessing, time
cmdStr = 'python ./tst1.py'
print(cmdStr)
cmdList = cmdStr.split()
subProc = subprocess.Popen(cmdList, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

while(1):
    # this call blocks until tst1.py has completed, then reads all the output
    # it then reads empty lines (seemingly for ever)
    ln = subProc.stdout.readline()
    if ln:
        print(ln)

tst1.py は単純にループしてメッセージを出力します: #!/usr/bin/env python import time

if __name__ == "__main__":
    x = 0
    while(x<20):
        print("%d: sleeping ..." % x)
        # flushing stdout here fixes the problem
        #sys.stdout.flush()
        time.sleep(1)
        x += 1

tst1.py がシェル スクリプト tst1.sh として記述されている場合:

#!/bin/bash
x=0

while [ $x -lt 20 ]
do
    echo $x: sleeping ...
    sleep 1
    let x++
done

readline() は期待どおりに動作します。

いくつか遊んだ後、tst1.py の stdout をフラッシュすることで状況を解決できることを発見しましたが、なぜこれが必要なのかわかりません。誰かがこの動作について説明したかどうか疑問に思っていましたか?

Redhat 4 Linux を実行しています: Linux lb-cbga-05 2.6.9-89.ELsmp #1 SMP Mon Apr 20 10:33:05 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

4

1 に答える 1

0

出力がどこかにバッファリングされている場合、その時点で子プロセスが存在するまで親プロセスはそれを認識しないため、出力はフラッシュされ、すべてのfdが閉じられます。ほとんどのシェルを入力すると、実際に実行され(何かを出力する)プロセスをフォークして存在するため、出力もフラッシュされるため、出力を明示的にフラッシュせずにbashで動作する理由については。echoecho

于 2012-11-14T15:57:55.437 に答える