web-dev-qa-db-ja.com

サブプロセスstderrをstdoutにリダイレクトします

サブプロセスのstderr出力をstdoutにリダイレクトしたい。定数 STDOUT はそれを行うべきです、そうではありませんか?

しかしながら、

$ python >/dev/null -c 'import subprocess;\
                        subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'

doesは何かを出力します。なぜそうなのですか、また標準出力でエラーメッセージを取得する方法は?

34
phihag

ソースコード をよく読んで答えが得られます。特に、 documentation は次のような場合に誤解を招く可能性があります。

subprocess.STDOUT
特別な値(...)は、標準エラーが標準出力と同じhandleに入ることを示します。

-1が評価されるとき、stdoutは "default"(技術的にはstderr=subprocess.STDOUT)に設定されるため、stderrも "default"に設定されます。残念ながら、これはstderrの出力がまだstderrに送られることを意味します。

問題を解決するには、subprocess.STDOUTの代わりにstdoutファイルを渡します。

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.buffer)'

または、Pythonのレガシー2.xバージョンとの互換性:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.fileno())'
35
phihag

実際には、subprocess.STDOUT正確にドキュメントに記載されていることを行います。stderrをstdoutにリダイレクトします。

proc = subprocess.Popen(self.task["command"], Shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ""
while (True):
    # Read line from stdout, break if EOF reached, append line to output
    line = proc.stdout.readline()
    line = line.decode()
    if (line == ""): break
    output += line

結果は、stdoutとstderrの両方からのプロセスの出力を含む変数outputになります。

stderr=subprocess.STDOUTは、すべてのstderr出力をリダイレクトします直接呼び出しプロセスのstdoutに、これは大きな違いです。

15
Maxxim