使 Python 记录器将所有消息输出到标准输出以及日志文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14058453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Making Python loggers output all messages to stdout in addition to log file
提问by
Is there a way to make Python logging using the loggingmodule automatically output things to stdout in additionto the log file where they are supposed to go? For example, I'd like all calls to logger.warning, logger.critical, logger.errorto go to their intended places but in addition always be copied to stdout. This is to avoid duplicating messages like:
有没有办法使用,使Python记录logging模块自动输出到标准输出,除了在那里它们应该去的日志文件?例如,我希望所有对logger.warning、logger.critical、 的调用都logger.error转到其预期位置,但另外始终复制到stdout。这是为了避免重复消息,例如:
mylogger.critical("something failed")
print "something failed"
采纳答案by Martijn Pieters
All logging output is handled by the handlers; just add a logging.StreamHandler()to the root logger.
所有日志输出都由处理程序处理;只需将 a 添加logging.StreamHandler()到根记录器。
Here's an example configuring a stream handler (using stdoutinstead of the default stderr) and adding it to the root logger:
这是配置流处理程序(使用stdout而不是默认stderr)并将其添加到根记录器的示例:
import logging
import sys
root = logging.getLogger()
root.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
root.addHandler(handler)
回答by Alok Singh Mahor
It's possible using multiple handlers.
可以使用多个处理程序。
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)
Please see: https://docs.python.org/2/howto/logging-cookbook.html
回答by Eyal
The simplest way to log to stdout:
登录到标准输出的最简单方法:
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
回答by Weidenrinde
The simplest way to log to file and to stderr:
记录到文件和 stderr 的最简单方法:
import logging
logging.basicConfig(filename="logfile.txt")
stderrLogger=logging.StreamHandler()
stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().addHandler(stderrLogger)
回答by Anton Protopopov
You could create two handlers for file and stdout and then create one logger with handlersargument to basicConfig. It could be useful if you have the same log_level and format output for both handlers:
您可以为 file 和 stdout 创建两个处理程序,然后创建一个handlers参数为 的记录器basicConfig。如果两个处理程序具有相同的 log_level 和 format 输出,这可能很有用:
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')
回答by Elias Strehle
Here is a solution based on the powerful but poorly documented logging.config.dictConfigmethod.
Instead of sending every log message to stdout, it sends messages with log level ERRORand higher to stderrand everything else to stdout.
This can be useful if other parts of the system are listening to stderror stdout.
这是一个基于强大但记录不足的logging.config.dictConfig方法的解决方案。它不是将每条日志消息都发送到stdout,而是将具有日志级别ERROR和更高级别的消息发送到 以及将其他所有消息发送stderr到stdout。如果系统的其他部分正在侦听stderr或 ,这会很有用stdout。
import logging
import logging.config
import sys
class _ExcludeErrorsFilter(logging.Filter):
def filter(self, record):
"""Filters out log messages with log level ERROR (numeric value: 40) or higher."""
return record.levelno < 40
config = {
'version': 1,
'filters': {
'exclude_errors': {
'()': _ExcludeErrorsFilter
}
},
'formatters': {
# Modify log message format here or replace with your custom formatter class
'my_formatter': {
'format': '(%(process)d) %(asctime)s %(name)s (line %(lineno)s) | %(levelname)s %(message)s'
}
},
'handlers': {
'console_stderr': {
# Sends log messages with log level ERROR or higher to stderr
'class': 'logging.StreamHandler',
'level': 'ERROR',
'formatter': 'my_formatter',
'stream': sys.stderr
},
'console_stdout': {
# Sends log messages with log level lower than ERROR to stdout
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'my_formatter',
'filters': ['exclude_errors'],
'stream': sys.stdout
},
'file': {
# Sends all log messages to a file
'class': 'logging.FileHandler',
'level': 'DEBUG',
'formatter': 'my_formatter',
'filename': 'my.log',
'encoding': 'utf8'
}
},
'root': {
# In general, this should be kept at 'NOTSET'.
# Otherwise it would interfere with the log levels set for each handler.
'level': 'NOTSET',
'handlers': ['console_stderr', 'console_stdout', 'file']
},
}
logging.config.dictConfig(config)
回答by Lexander
Since no one has shared a neat two liner, I will share my own:
由于没有人分享过整齐的两行,我将分享我自己的:
logging.basicConfig(filename='logs.log', level=logging.DEBUG, format="%(asctime)s:%(levelname)s: %(message)s")
logging.getLogger().addHandler(logging.StreamHandler())
回答by Kiki Jewell
Here's an extremely simple example:
这是一个非常简单的例子:
import logging
l = logging.getLogger("test")
# Add a file logger
f = logging.FileHandler("test.log")
l.addHandler(f)
# Add a stream logger
s = logging.StreamHandler()
l.addHandler(s)
# Send a test message to both -- critical will always log
l.critical("test msg")
The output will show "test msg" on stdout and also in the file.
输出将在标准输出和文件中显示“test msg”。

