2017-05-19 26 views
1

少々のコードでは、多くのことが起こっています。私はこれを簡潔に保つようにします。サブプロセスstdoutとstderrをログファイルにキャプチャするためのPython関数

私は、外部プログラムを実行し、stdoutとstderrの両方をログファイルに送るPython関数を持っています。

私は関数をテストするためにdoctestを使用しています。出力キャプチャ機能をテストする必要があります。以下のコードは、関数とテストを記述しようとしています。テストは失敗し、ログファイルには何も書き込まれません。問題がテストにあるのか、テスト中のコードにあるのか、あるいはその両方にあるのかどうかはわかりません。提案?

from __future__ import print_function 

import subprocess 

def run(command_line, log_file): 
    """ 
    # Verify stdout and stderr are both written to log file in chronological order 
    >>> run("echo text to stdout; echo text to stderr 1>&2", "log") 
    >>> f = open("log"); out = f.read(); f.close() 
    >>> print(out.strip()) 
    text to stdout 
    text to stderr 
    """ 
    command_line = "set -o pipefail; " + command_line + " 2>&1 | tee " + log_file 

    # Run command. Wait for command to complete. If the return code was zero then return, otherwise raise CalledProcessError 
    subprocess.check_call(command_line, shell=True, executable="bash") 

試験結果:2標準出力/標準エラー出力をリダイレクトして、shell=Truesubprocess.check_callをやって以来

$ python -m doctest testclass.py 
text to stdout 
text to stderr 
********************************************************************** 
File "testclass.py", line 10, in testclass.run 
Failed example: 
    print(out.strip()) 
Expected: 
    text to stdout 
    text to stderr 
Got: 
    <BLANKLINE> 
********************************************************************** 
1 items had failures: 
    1 of 3 in testclass.run 
***Test Failed*** 1 failures. 
+0

あなたがた結果bashコマンドを試してみました'' set -o pipefail; "+ command_line +" 2>&1 | tee " + log_file'を端末に挿入しますか?出力はどのように見えますか? –

+0

端末に送信されるテキストは、次のコマンドで期待どおりになります。set -o pipefail; stdoutにテキストをエコーし​​ます。テキストをstderrにエコーします。1>&2 2>&1 | tee log – Steve

+0

@ Jean-FrançoisFabreこれは、処理結果を調べるためにユーザーが必要とする大きなログファイルを生成する大きなバッチ処理の小さな部分の1つです。 – Steve

答えて

2

teeは、コマンドを実行し、出力をキャプチャするための最良の方法ではありませんが(実際にはそれが一番近いです最悪に)、私はそれが失敗するのは本当に驚きではありません。

私のソリューションは、(私はまだあなた理由を困惑しています(ここでリターンコードをチェックする必要はありません)スタータ用set -o pipefailをドロップすると、他のリダイレクト/ティーは最後のものだけに適用され、括弧内の両方のコマンドをラップすることです

command_line = "(" + command_line + ") 2>&1 | tee " + log_file 

そして、あなたはpipefail事を復元しなければならなかった場合は、括弧内にそれを実行します:)しかし、正直に言うと、何も出力アルすべてを取得しない

command_line = "(set -o pipefail; " + command_line + ") 2>&1 | tee " + log_file 
+0

彼は実際には単に空であったかもしれないログファイルに 'stderr'テキストを効果的にパイプしていたので、彼は全く出力がないと思います。 –

+0

@ThomasKühnしかし、彼は 'stderr 1>&2'に' echo text to&2'をしていました。それはstderrにテキストを発行することになっています。 –

+1

そう、私はその部分を逃した。それは例をとらないでテストするのは難しいです。さて、それは今解決されました;) –

関連する問題