shellpy と呼ばれる Windows 用の単純なシェルの代替品を作成しています (学習目的で)。明らかに、シェルを Windows CMD から独立させたいので、すべての出力を StringIO オブジェクトにリダイレクトしています。これまでのところ、かなりうまく機能しています。
しかし、小さなシェル内で Python インタラクティブ インタープリターを実行しているときに問題が発生しました。明らかに、対話型インタープリターは、 stdoutに書き込む印刷出力を除いて、すべてをstderrに書き込みます。私のアプローチでは、次のような出力が得られます。
シェルピー - shellpy $ python Python 2.7.3 (デフォルト、...) [MSC v.1500 64 ビット (AMD64)] (win32) 詳細については、「ヘルプ」、「著作権」、「クレジット」、または「ライセンス」と入力してください。 >>> print "Hello, world!" こんにちは、世界! >>>
私はこれを理解することはできません。私のコードを理解する方法は次のとおりです。子プロセスの stdout または stderr によって 1 バイトのデータが書き込まれるたびに、シェルの適切な印刷機能にリダイレクトされます。では、なぜ両者が重なり合うのでしょうか。確かに、Python インタープリターは両方のファイル記述子に同時に書き込みを行っていませんか? 私のアプローチに欠陥がありますか?もしそうなら、子プロセスの出力をどのようにリダイレクトすればよいですか?
注:質問のタイトルで私の問題を説明するのに非常に苦労しました。より良いものを考えられる場合は、自由に編集してください。
このコードはサブプロセスを起動します:
child = subprocess.Popen(
[command] + args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Redirect the child's output to the shell.
redirect_pipe_output(child.stdout, self.print_text)
redirect_pipe_output(child.stderr, self.print_error)
# Wait for the child to finish.
child.wait()
これは、スレッドを使用して継続的に子をポーリングして出力するリダイレクト関数です。
def redirect_pipe_output(fileobject, fn):
"""Creates a new thread and continuously tries to read from the input file
object. When data is read from the file object, `fn` is called with that
data."""
def work():
try:
while True:
fn(fileobject.read(1))
except ValueError:
pass
t = threading.Thread(target=work)
t.daemon = True
t.start()
関数self.print_text
とself.print_error
は現在、 の単なるラッパーですsys.stdout.write
。