2012-12-27 11 views
257

モジュールを使用してPythonログを出力すると、標準出力に自動的に出力されますログファイルには、たとえば、logger.warninglogger.criticallogger.errorへのすべての通話は、意図した場所に移動するだけでなく、常にstdoutにコピーしてください。これは、メッセージの重複を避けるためです。Pythonロガーはログに加えてすべてのメッセージをstdoutに出力する

mylogger.critical("something failed") 
print "something failed" 
+0

この回答を確認してくださいhttps://stackoverflow.com/questions/9321741/printing-to-screen-and-writing-to -a-file-at-the-time – SeF

答えて

369

すべてのログ出力はハンドラによって処理されます。ルートロガーにlogging.StreamHandler()を追加するだけです。

ここでは例として(代わりにデフォルトstderrstdoutを使用して)ストリームハンドラを設定してルートロガーに追加です:

import logging 
import sys 

root = logging.getLogger() 
root.setLevel(logging.DEBUG) 

ch = logging.StreamHandler(sys.stdout) 
ch.setLevel(logging.DEBUG) 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 
ch.setFormatter(formatter) 
root.addHandler(ch) 
+3

これはうまくいっていますが、既にファイルにリダイレクトされている場合、どうすればそれを '' stdout''に出力することができますか? – user248237dfsf

+31

@ user248237:図のように* new *ハンドラを追加します。新しいハンドラは既存のハンドラを置き換えず、ログエントリも処理します。 –

+0

@MartijnPietersには、すべてのログステートメントに文字列を追加する方法がありますか? –

41

これは、複数のハンドラを使用可能です。

import logging 
import auxiliary_module 

# create logger with 'spam_application' 
log = logging.getLogger('spam_application') 
log.setLevel(logging.DEBUG) 

# create formatter and add it to the handlers 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 

# create file handler which logs even debug messages 
fh = logging.FileHandler('spam.log') 
fh.setLevel(logging.DEBUG) 
fh.setFormatter(formatter) 
log.addHandler(fh) 

# create console handler with a higher log level 
ch = logging.StreamHandler() 
ch.setLevel(logging.ERROR) 
ch.setFormatter(formatter) 
log.addHandler(ch) 

log.info('creating an instance of auxiliary_module.Auxiliary') 
a = auxiliary_module.Auxiliary() 
log.info('created an instance of auxiliary_module.Auxiliary') 

log.info('calling auxiliary_module.Auxiliary.do_something') 
a.do_something() 
log.info('finished auxiliary_module.Auxiliary.do_something') 

log.info('calling auxiliary_module.some_function()') 
auxiliary_module.some_function() 
log.info('done with auxiliary_module.some_function()') 

# remember to close the handlers 
for handler in log.handlers: 
    handler.close() 
    log.removeFilter(handler) 

ご覧ください。https://docs.python.org/2/howto/logging-cookbook.html

+4

ちょっと厄介ですが、すばらしい答えです。ストリームとファイルのさまざまなレベルとフォーマットの使い方をどのように表示するのが大好きです。 +1、しかし+2精神。 –

254

最も簡単な方法:

import logging 
import sys 
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) 
+34

しかし、これはファイルに記録されていませんか?問題はコンソールにファイル_and_へのログ記録を行う方法でした。 – Weidenrinde

+8

これはOPが求めていたものではないかもしれませんが、私が探していたものとGoogleの最初のヒットです。 +1 – phoenix

+0

おそらく答えは必要ですが、尋ねられたものはありません :-P –

23

ファイルとstderrにログインするための最も簡単な方法:

import logging 
    logging.basicConfig(filename="logfile.txt") 
    stderrLogger=logging.StreamHandler() 
    stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT)) 
    logging.getLogger().addHandler(stderrLogger) 
+0

コンソールにログメッセージが表示される前に、INFO、DEBUG、およびERRORのラベルは表示されません。ファイル内のラベルを表示します。コンソールにラベルを表示するためのアイデアはありますか? –

+1

ありがとう、@ JahMyst、私はFormatterを追加しました。残念ながら、それは短くはありませんが、最も単純な方法です。 :-) – Weidenrinde

+0

ありがとう、それは素晴らしいです! –

-13

ハックが、単純:

def print_n_log(msg,f): 
    f.write(msg + "\n") 
    print msg 
f = open("log_output.txt","w") 

あなたは何かがちょうど

print_n_log("my message, hark!", f) 

を呼び出し、その後でログファイルを閉じるスクリプトの最後ログイン+印刷する必要があるとき:

f.close() 
+0

...ログに加えて! – kame

9

あなたはファイルとstdoutのための2つのハンドラを作成することができますhandlers引数を使用してbasicConfigに1つのロガーを作成します。あなたは、両方のハンドラの同じLOG_LEVELとフォーマット出力を持っている場合、それは役に立つかもしれません:

import logging 
import sys 

file_handler = logging.FileHandler(filename='tmp.log') 
stdout_handler = logging.StreamHandler(sys.stdout) 
handlers = [file_handler, stdout_handler] 

logging.basicConfig(
    level=logging.DEBUG, 
    format='[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s', 
    handlers=handlers 
) 

logger = logging.getLogger('LOGGER_NAME') 
関連する問題