2012-12-17 8 views
5

私は研究ツールを書いていますが、最近は "print"ステートメントの使用からPythonに組み込まれたロガー機能の使用に切り替えました。これは私が推論したところでは、出力をファイルにダンプするオプションと、スクリーンにダンプするオプションをユーザーに与えることができます。外部アプリケーションからのログ

これまでのところとても良いです。私のコードのPythonにある部分は、 "logger.info"と "logger.error"を使って画面とファイルの両方にダンプします。 "logger"はモジュール全体のロガーです。この部分は魅力のように機能します。

しかし、私はいくつかの点で、 "subprocess.call"を使ってシェルを通して実行可能ファイルを実行します。だから、コード全体、私は、このコマンドの出力は、いつものように、画面に印刷し

proc = subprocess.call(command) 

のようなラインを持っているが、それは、ユーザーが指定したファイルにダンプしないでしょう。

一つの可能​​なオプションは、ファイルへのパイプを開くために、次のようになります。

proc = subprocess.call(command, stdout=f, stderr=subprocess.OUTPUT) 

しかし、それは唯一の画面にファイルにダンプしないでしょう。

基本的に、私の質問は次のとおりです:subprocess.call専用のファイルの別のハンドラーを構築する必要なく、既存のロガーを活用できる方法はありますか? (おそらく、出力をロガーにリダイレクトすることによって)?あるいは、現在の設定ではこれは不可能ですか?後者の場合、セットアップをどのように改善できますか?

(それらが受信されると実行ファイルからのメッセージが記録されるようにロギングは、「リアルタイム」にした場合ああ、また、それは素晴らしいことだ。)任意の助け

ありがとう! :)

+1

あなたの状況では、Lennart Regebroの[StreamLoggerクラス](http://stackoverflow.com/a/4838875/190597)がうまく動作します。 – unutbu

+0

参考になりました!これは私の場合にはうまくいく。 –

答えて

3

stdoutをファイルにパイプするのではなく、PIPEにパイプし、そのパイプから読み込んでロガーに書き込むことができます。このような何か:

proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.OUTPUT) 
for line in proc.stdout: 
    logging.info(line) 

はしかし、さらに簡単な答えがあります:あなたは、ファイルハンドルを持つファイルのようなオブジェクトを使用する必要がありますが、あなたはloggingに各ラインを通るパイプの最上部に1つずつ作成することができます。あなたはこのオブジェクトを自分で書くことができますが、@unutbuの言うとおり、誰かが既にthis questionでそれを行っています。だから、:

もちろん
with StreamLogger(logging.INFO) as out: 
    proc = subprocess.call(command, stdout=out, stderr=subprocess.OUTPUT) 

あなたはまた、一時的にthis confusingly identically-named classを使用して、例えば、ロガーへの書き込みだけを介して出力を渡すためにstdoutをラップすることができます:

with StreamLogger('stdout'): 
    proc = subprocess.call(command, stderr=subprocess.OUTPUT) 
+0

最後のリンクのコードを参考にしていただきありがとうございます。それは面白い読書でした。 –

3

unutbu's commentは良好です。あなたはLennart's answerを見てください。

teeの機能のようなものですが、subprocessモジュールはOSハンドルのレベルで動作します。つまり、サブプロセスによって書き込まれたデータはPythonコードでは見られません。どのようなログを記録し、何が書かれていても印刷します。

レナートの答えを使用するだけでなく、sarge(公開:私はそのメンテナーです)のような第三者のライブラリを使ってこのようなことを行うことができます。ロギング以上の機能を果たします。

# echotest.py 
import time 
for i in range(10): 
    print('Message %d' % (i + 1)) 

、あなたは、あなたのスクリプトでそれをキャプチャし、それをログに記録し、それを画面に印刷したい:あなたのような、出力を生成するプログラムがあるとし

#subptest.py 
from sarge import capture_stdout 
import logging 
import sys 

logging.basicConfig(filename='subptest.log', filemode='w', 
        level=logging.INFO) 

p = capture_stdout('python echotest.py', async=True) 
while True: 
    line = p.stdout.readline() 
    line = line.strip() 
    # depending on how the child process generates output, 
    # sometimes you won't see anything for a bit. Hence only print and log 
    # if you get something 
    if line: 
     print(line) 
     logging.info(line) 

    # Check to see when we can stop - after the child is done. 
    # The return code will be set to the value of the child's exit code, 
    # so it won't be None any more. 

    rc = p.commands[0].process.poll() 
    # if no more output and subprocess is done, break 
    if not line and rc is not None: 
     break 

あなたは上記のスクリプトを実行した場合

$ python subptest.py 
Message 1 
Message 2 
Message 3 
Message 4 
Message 5 
Message 6 
Message 7 
Message 8 
Message 9 
Message 10 

そして、我々は、ログファイルをチェックインするとき、私たちは以下を参照してください:

、あなたはコンソールにプリントアウトします
+0

チップをありがとう! :) –

関連する問題