13

Pythonスクリプトは、Linux上の外部アプリケーションを制御し、パイプを介して外部アプリケーションstdinに入力を渡し、外部アプリケーションstdoutからパイプを介して出力を読み取ります。

問題は、パイプへの書き込みが行ではなくブロックによってバッファリングされるため、制御スクリプトが外部アプリケーションのprintfなどによって出力されたデータを受信する前に遅延が発生することです。

外部アプリケーションを変更して、明示的なfflush(0)呼び出しを追加することはできません。

これを実現するために、Python標準ライブラリのptyモジュールをサブプロセスモジュールとどのように使用できますか?

4

7 に答える 7

6

PTY を使用して、次の方法でこれを解決できます。

  • pty マスター/スレーブ ペアの作成;
  • 子プロセスの stdin、stdout、および stderr を pty スレーブ デバイスに接続します。
  • 親の pty マスターからの読み取りと書き込み。
于 2009-10-10T11:56:37.147 に答える
5

これを行うことは可能ですが、私が考えることができる唯一の解決策は、かなり複雑で、移植性がなく、おそらく問題のある詳細に満ちていることです。LD_PRELOAD を使用して、setvbuf を呼び出して stdout のバッファを解除するコンストラクタを含む動的ライブラリを外部アプリケーションにロードさせることができます。また、アプリケーションが独自の stdout を明示的にバッファリングするのを防ぐために、ライブラリで setvbuf をラップすることも必要になるでしょう。また、呼び出しごとにフラッシュするように、fwrite と printf をラップする必要があります。プリロードされる .so を記述すると、Python の外に移動します。

于 2009-10-09T15:58:32.303 に答える
3

ありえないと思います。ソース アプリケーションが発信バッファーをフラッシュしない場合、バッファーがオーバーフローしてフラッシュが強制されるまで、データはそのプロセスの外部に到達しません。

fileなどの確立されたコマンドには、出力を明示的にフラッシュするオプション (-n) があることに注意してください。これは、入力ファイル名をパイプから読み取り、検出されたタイプを出力するモードで file を使用する場合に必要です。このモードでは、終了時にファイル プログラムが終了しないため、出力は表示されません。

これを下位レベルで考えてみてください。出力バッファリングとはwrite()、バッファリングされたストリームで実行すると、バッファがいっぱいになるまで、または (通常は) 改行が見つかるまで、データがメモリ内バッファにコピーされることを意味します。次に、オーバーフローまたは改行までのバッファーの部分がwrite()、基になるシステムレベルのファイル記述子 (ファイル、パイプ、ソケットなど) に書き込まれます。

外部からそのプログラムにバッファをフラッシュするよう説得する方法がわかりません。

于 2009-10-09T14:36:23.463 に答える
2

この質問への回答が役立つ場合があります。

Pythonデーモンサブプロセスを実行してstdoutを読み取る

同じ問題に取り組んでいるようです。

于 2011-06-07T19:07:53.740 に答える
2

一部のプログラムは、出力が「実際のユーザー」(つまり tty) に送信されないと思われる場合にのみ出力をバッファリングすることに注意してください。出力が別のプログラムによって読み取られていることを検出すると、バッファリングします。

tty のエミュレーションは、Expectが他のプロセスを自動化する際に行うことの 1 つです。

Expect の純粋な Python 実装がありますが、tty エミュレーションをどの程度うまく処理できるかはわかりません。

于 2009-10-09T16:02:16.643 に答える
1

この質問は少し古いですが、実行したいコマンドでサブプロセスを使用してstdbufを呼び出すことで、問題を解決できると思います。

于 2012-02-28T06:50:45.000 に答える
-1

-u 引数を指定して Python インタープリターを実行してみてください。

python -u myscript.py

これにより、Python はバッファリングされていない stdin/stdout を使用するようになり、これが役立つ場合があります。

于 2009-10-09T14:33:28.413 に答える