Python スクリプトから Python インタープリターや CMD.EXE の出力をキャプチャするにはどうすればよいですか?
質問
- Python スクリプトから Python インタープリターの出力をキャプチャすることは可能ですか?
- Python スクリプトから Windows CMD の出力をキャプチャすることはできますか?
もしそうなら、どのライブラリを調べればよいでしょうか?
解決
スクリプトの「親」である Python インタープリターまたは CMD.exe について話しているのであれば、それは不可能です。すべての POSIX 風のシステム (現在 Windows を実行しているようですが、YMMV という私にはわかりません) には、各プロセスに 3 つのストリーム (標準入力、標準出力、標準エラー) があります。デフォルトでは (コンソールで実行している場合)、これらはコンソールに送信されますが、パイプ表記を使用してリダイレクトすることも可能です。
python script_a.py | python script_b.py
これにより、スクリプト a の標準出力ストリームがスクリプト B の標準入力ストリームに関連付けられます。この例でも、標準エラーはコンソールに表示されます。に関する記事を参照してください。 標準ストリーム ウィキペディアで。
子プロセスについて話している場合は、次のように Python から起動できます (双方向通信が必要な場合は、stdin もオプションです)。
import subprocess
# Of course you can open things other than python here :)
process = subprocess.Popen(["python", "main.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x = process.stderr.readline()
y = process.stdout.readline()
process.wait()
パイソンを参照 サブプロセス プロセスの管理に関する情報については、モジュールを参照してください。通信の場合、process.stdin パイプと process.stdout パイプは標準とみなされます。 ファイルオブジェクト.
パイプで使用する場合、標準入力から次のように読み取ります。 ラセフク 次のようなことをすることを提案しました:
import sys
x = sys.stderr.readline()
y = sys.stdin.readline()
sys.stdin と sys.stdout は、上記の標準ファイル オブジェクトであり、 システム モジュール。こちらもご覧ください。 パイプ モジュール。
ただし、この例のように readline() を使用してデータを読み取るのは、データを取得する非常に単純な方法です。出力が行指向でない、または不決定的である場合は、おそらく調べた方がよいでしょう。 投票 残念ながら、これは Windows では機能しませんが、代替手段があると思います。
他のヒント
私はあなたの質問の最初の部分に対する良い答えを指摘できると思います。
1.   PythonからPythonインタープリターの出力をキャプチャすることは可能ですか スクリプト?
答えは" yes "であり、個人的には PEP 343-「と」ステートメント 文書。
from contextlib import contextmanager
import sys
@contextmanager
def stdout_redirected(new_stdout):
saved_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout.close()
sys.stdout = saved_stdout
次のように使用します:
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
素晴らしい点は、スクリプト全体の範囲ではなく、スクリプトの実行の一部のみに選択的に適用でき、未処理の例外がコンテキスト内で発生した場合でも有効であるということです。初めて使用した後に追加モードでファイルを再度開くと、結果を1つのファイルに蓄積できます。
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
print "screen only output again"
with stdout_redirected(open("filename.txt", "a")):
print "Hello world2"
もちろん、上記を拡張して sys.stderr
を同じファイルまたは別のファイルにリダイレクトすることもできます。関連する質問への回答もご覧ください。
実際には、間違いなくできますが、同時に美しく、く、クレイジーです!
sys.stdoutおよびsys.stderrを、出力を収集するStringIOオブジェクトに置き換えることができます。
例を示します。evil.pyとして保存します。
import sys
import StringIO
s = StringIO.StringIO()
sys.stdout = s
print "hey, this isn't going to stdout at all!"
print "where is it ?"
sys.stderr.write('It actually went to a StringIO object, I will show you now:\n')
sys.stderr.write(s.getvalue())
このプログラムを実行すると、次のことがわかります:
- 標準出力には何もありません(通常はprintが出力される)
- stderrに書き込まれる最初の文字列は、「It」で始まるものです
- 次の2行は、StringIOオブジェクトで収集されたものです
sys.stdout / errをこのように置き換えることは、monkeypatchingと呼ばれるもののアプリケーションです。これは「サポート」されているかどうかによって意見が異なり、間違いなくdefinitelyいハックですが、外部のものを1回または2回ラップしようとするとベーコンが節約されます。
WindowsではなくLinuxでテスト済みですが、同様に機能するはずです。 Windowsで動作するかどうか教えてください!
サブプロセスが必要です。特に17.1.1のPopenを見て、17.1.2で通信します。
どのコンテキストで質問していますか
コマンドラインで起動するプログラムからの出力をキャプチャしようとしていますか?
もしそうなら、これはそれを実行する方法です:
somescript.py | your-capture-program-here
そして出力を読むには、標準入力から読みます。
一方で、そのスクリプトまたはcmd.exeなどをプログラム内から実行していて、スクリプト/プログラムが終了するまで待機し、そのすべての出力をキャプチャする場合は、その外部プログラムを起動するために使用するライブラリ呼び出しで、おそらく出力を読んで完了を待つ方法を与えるように依頼する方法があります。