I'm using Python's logging module to log some debug strings to a file which works pretty well. Now in addition, I'd like to use this module to also print the strings out to stdout. How do I do this? In order to log my strings to a file I use following code:
我正在使用Python的日志模块将一些调试字符串记录到一个运行良好的文件中。另外,我还想用这个模块把字符串输出到stdout。我该怎么做呢?为了将我的字符串记录到一个文件中,我使用以下代码:
import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
and then call a logger function like
然后调用一个记录器函数
logger.debug("I am written to the file")
Thank you for some help here!
谢谢您的帮助!
5 个解决方案
#1
257
Just get a handle to the root logger and add the StreamHandler. The StreamHandler writes to stderr. Not sure if you really need stdout over stderr, but this is what I use when I setup the Python logger and I also add the FileHandler as well. Then all my logs go to both places (which is what it sounds like you want).
只需获取根日志记录器的句柄并添加StreamHandler。StreamHandler写入stderr。不确定是否真的需要stderr上的stdout,但这是我在设置Python日志记录器时使用的,我还添加了FileHandler。然后我所有的日志都到这两个地方去了(这就是你想要的)。
import logging
logging.getLogger().addHandler(logging.StreamHandler())
You could also add a Formatter to it so all your log lines have a common header.
您还可以向它添加格式化程序,以便所有日志行都有一个公共的头。
ie:
即:
import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
rootLogger = logging.getLogger()
fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)
Prints to the format of:
打印格式为:
2012-12-05 16:58:26,618 [MainThread ] [INFO ] my message
#2
46
Adding a StreamHandler without arguments goes to stderr instead of stdout. If some other process has a dependency on the stdout dump (i.e. when writing an NRPE plugin), then make sure to specify stdout explicitly or you might run into some unexpected troubles.
添加一个没有参数的StreamHandler给stderr而不是stdout。如果其他进程依赖于stdout转储(例如在编写NRPE插件时),那么请确保显式地指定stdout,否则您可能会遇到一些意外的麻烦。
Here's a quick example reusing the assumed values and LOGFILE from the question:
这里有一个简单的例子,重用问题中的假设值和日志文件:
import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys
log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)
#3
41
logging.basicConfig()
can take a keyword argument handlers
since Python 3.3, which simplifies logging setup a lot, especially when setting up multiple handlers with the same formatter:
logging.basicConfig()可以使用自Python 3.3以来的关键字参数处理程序,这简化了日志设置,特别是在设置多个处理程序时,使用相同的格式化程序:
handlers
– If specified, this should be an iterable of already created handlers to add to the root logger. Any handlers which don’t already have a formatter set will be assigned the default formatter created in this function.处理程序——如果指定,这应该是已创建的处理程序的可迭代性,以便添加到根日志记录器中。任何没有格式化程序集的处理程序都将被分配到在这个函数中创建的默认格式化程序。
The fairly long and verbose example code from the accepted answer therefore becomes just this:
因此,从已接受的答案中得到的相当长的、冗长的示例代码就变成了:
import logging
logging.basicConfig(
format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s",
handlers=[
logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
logging.StreamHandler()
])
(Or with import sys
+ StreamHandler(sys.stdout)
per original question's requirements.)
(或使用import sys + StreamHandler(sys.stdout)来满足原始问题的需求。)
#4
16
Either run basicConfig
with stream=sys.stdout
as the argument prior to setting up any other handlers or logging any messages, or manually add a StreamHandler
that pushes messages to stdout to the root logger (or any other logger you want, for that matter).
使用stream=sys运行basicConfig。stdout作为设置任何其他处理程序或记录任何消息之前的参数,或者手动添加一个StreamHandler,该处理程序将消息推送到根日志记录器(或者您想要的任何其他日志记录器)。
#5
-2
For 2.7, try the following:
对于2.7,试一下:
fh = logging.handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
#1
257
Just get a handle to the root logger and add the StreamHandler. The StreamHandler writes to stderr. Not sure if you really need stdout over stderr, but this is what I use when I setup the Python logger and I also add the FileHandler as well. Then all my logs go to both places (which is what it sounds like you want).
只需获取根日志记录器的句柄并添加StreamHandler。StreamHandler写入stderr。不确定是否真的需要stderr上的stdout,但这是我在设置Python日志记录器时使用的,我还添加了FileHandler。然后我所有的日志都到这两个地方去了(这就是你想要的)。
import logging
logging.getLogger().addHandler(logging.StreamHandler())
You could also add a Formatter to it so all your log lines have a common header.
您还可以向它添加格式化程序,以便所有日志行都有一个公共的头。
ie:
即:
import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
rootLogger = logging.getLogger()
fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)
Prints to the format of:
打印格式为:
2012-12-05 16:58:26,618 [MainThread ] [INFO ] my message
#2
46
Adding a StreamHandler without arguments goes to stderr instead of stdout. If some other process has a dependency on the stdout dump (i.e. when writing an NRPE plugin), then make sure to specify stdout explicitly or you might run into some unexpected troubles.
添加一个没有参数的StreamHandler给stderr而不是stdout。如果其他进程依赖于stdout转储(例如在编写NRPE插件时),那么请确保显式地指定stdout,否则您可能会遇到一些意外的麻烦。
Here's a quick example reusing the assumed values and LOGFILE from the question:
这里有一个简单的例子,重用问题中的假设值和日志文件:
import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys
log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)
#3
41
logging.basicConfig()
can take a keyword argument handlers
since Python 3.3, which simplifies logging setup a lot, especially when setting up multiple handlers with the same formatter:
logging.basicConfig()可以使用自Python 3.3以来的关键字参数处理程序,这简化了日志设置,特别是在设置多个处理程序时,使用相同的格式化程序:
handlers
– If specified, this should be an iterable of already created handlers to add to the root logger. Any handlers which don’t already have a formatter set will be assigned the default formatter created in this function.处理程序——如果指定,这应该是已创建的处理程序的可迭代性,以便添加到根日志记录器中。任何没有格式化程序集的处理程序都将被分配到在这个函数中创建的默认格式化程序。
The fairly long and verbose example code from the accepted answer therefore becomes just this:
因此,从已接受的答案中得到的相当长的、冗长的示例代码就变成了:
import logging
logging.basicConfig(
format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s",
handlers=[
logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
logging.StreamHandler()
])
(Or with import sys
+ StreamHandler(sys.stdout)
per original question's requirements.)
(或使用import sys + StreamHandler(sys.stdout)来满足原始问题的需求。)
#4
16
Either run basicConfig
with stream=sys.stdout
as the argument prior to setting up any other handlers or logging any messages, or manually add a StreamHandler
that pushes messages to stdout to the root logger (or any other logger you want, for that matter).
使用stream=sys运行basicConfig。stdout作为设置任何其他处理程序或记录任何消息之前的参数,或者手动添加一个StreamHandler,该处理程序将消息推送到根日志记录器(或者您想要的任何其他日志记录器)。
#5
-2
For 2.7, try the following:
对于2.7,试一下:
fh = logging.handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)