2009-09-11 13 views
12

私は、すべてのオペレーティングシステムに適用可能なpopen(および関連するすべての関数)に関する一般的な質問を、PythonスクリプトまたはいくつかのCコードを記述し、コンソール(勝つかlinux)、私はすぐにプロセスからの出力を見ることができます。しかし、パイプにリダイレクトされたstdoutを持つフォークされたプロセスと同じ実行可能プログラムを実行すると、出力は親プロセスが読むことができるパイプに書き込まれる前に、通常4096バイトまでのどこかでバッファリングされます。サブプロセス出力をCまたはPythonでpopenでバッファリングすることをバイパスします

次のPythonスクリプトは、1024バイトのチャンクで出力を生成します

import os, sys, time 

if __name__ == "__main__": 
    dye = '@'*1024 
    for i in range (0,8): 
     print dye 
     time.sleep(1) 

前のスクリプトを実行し、それがバイト

によってパイプ、バイトに来るとすぐに出力を読み込みます次のPythonスクリプト
import os, sys, subprocess, time, thread 

if __name__ == "__main__": 
    execArgs = ["c:\\python25\\python.exe", "C:\\Scripts\\PythonScratch\\byte_stream.py"] 

    p = subprocess.Popen(execArgs, bufsize=0, stdout=subprocess.PIPE) 
    while p.returncode == None: 
     data = p.stdout.read(1) 
     sys.stdout.write(data) 
     p.poll() 

オペレーティングシステムのパスを調整します。この設定で実行すると、popenコマンドのバッファサイズが0に設定されているにもかかわらず、出力は1024のチャンクではなく、4096のチャンクで表示されます(これはデフォルトです)。誰も私にこの動作を変更する方法を教えてもらえますか?オペレーティングシステムがフォークされたプロセスの出力をコンソールから実行したときと同じように扱うようにする方法はありますか?バッファリングせずに?

答えて

14

一般的に、標準のCランタイムライブラリ(これは、すべてのシステムのすべてのプログラムのほぼすべてのプログラムの代わりに実行されます;-)は、stdoutが端末であるかどうかを検出します。そうでない場合は、出力をバッファリングします(これは、バッファリングされていない出力と比較して、非常に効率的です)。

書き込みを行っているプログラムを制御している場合は、(別の回答として)連続的にstdoutをフラッシュするか、(可能であればもっとエレガントに)stdoutを強制的にバッファリングしないでください。 -uコマンドラインフラグでのPythonを実行することによって:

-u  : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x) 
     see man page for details on internal buffering relating to '-u' 

(何manページを追加することはstdinとバイナリモード[S]との問題への言及です)。

書いているプログラムに触れたくない、または触れたくない場合は、読んでいるプログラムの-uなどが助けになることはほとんどありません(最も重要なバッファリングは作者の標準出力で起こります)読者の標準にあるものではない)。代わりに、pty標準ライブラリモジュールまたは上位レベルのサードパーティのpexpectモジュール(または、Windowsの場合は、そのプログラムが別のプログラムに書き込まれているにもかかわらず)を書き留めていると信じるように作家を欺くことですポートwexpect)。

+0

-u、喜びはありませんが、見通しは有望そうですね、ありがとう! –

+0

ちょうどフォローアップするには、pexpectは魅力のように動作し、wexpectはちょっとバギー(見つけにくい)ですが、仕事は終わります。これは私が最新バージョンのwexpectを見つけた場所です:http://sage.math.washington.edu/home/goreckc/sage/wexpect/ –

+0

Gearoidに感謝します。特に、wexpectは最新のバージョンに更新されていませんcode.google.com home、なぜだろうか! –

1

これは間違いなく、WindowsとLinuxの両方に適用され、popen()fopen()です。出力バッファを4096バイトより前に送出する場合は、fflush()(C言語)またはsys.stdout.flush()(Python)を使用してください。

+0

はい、これは私が現時点でやっていることですが、私の作業状況は、出力を生成するプロセスがユーザー定義であることを意味します。私は最初の質問でそれを述べておくべきです。 –

関連する問題