我有一个Python脚本,它使用'Print'打印到stdout。我最近通过Python Logger添加了日志记录,并希望如果启用了日志记录,这些打印语句将转到logger。我不想修改或删除这些打印语句。
我可以通过'log.info(“some info msg”)'来记录。我希望能够做到这样的事情:
if logging_enabled:
sys.stdout=log.info
print("test")
如果启用了日志记录,则应记录“test”,就像我执行log.info(“test”)一样。如果未启用日志记录,则只应将“test”打印到屏幕上。
这可能吗?我知道我可以以类似的方式将stdout指向文件(参见:redirect prints to log file)
答案 0 :(得分:19)
您有两种选择:
打开日志文件并用它替换sys.stdout,而不是函数:
log = open("myprog.log", "a")
sys.stdout = log
>>> print("Hello")
>>> # nothing is printed because it goes to the log file instead.
用日志功能替换打印:
# If you're using python 2.x, uncomment the next line
#from __future__ import print_function
print = log.info
>>> print("Hello!")
>>> # nothing is printed because log.info is called instead of print
答案 1 :(得分:9)
另一种方法是将记录器包装在一个对象中,该对象将对write
的调用转换为记录器的log
方法。
Ferry Boender在provided under the GPL license a post的his website中执行此操作https://studysoup.com/western-kentucky-university/econ-202/one-week-of-notes/econ-202-notes-week-9?id=864095:
import logging
import sys
class StreamToLogger(object):
"""
Fake file-like stream object that redirects writes to a logger instance.
"""
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger
self.log_level = log_level
self.linebuf = ''
def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
filename="out.log",
filemode='a'
)
stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO)
sys.stdout = sl
stderr_logger = logging.getLogger('STDERR')
sl = StreamToLogger(stderr_logger, logging.ERROR)
sys.stderr = sl
这使您可以轻松地将所有输出路由到您选择的记录器。如果需要,您可以在替换之前保存此线程中其他人提及的sys.stdout
和/或sys.stderr
,如果您需要稍后恢复它。
答案 2 :(得分:8)
当然,您可以打印到标准输出并附加到日志文件,如下所示:
# Uncomment the line below for python 2.x
#from __future__ import print_function
import logging
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger()
logger.addHandler(logging.FileHandler('test.log', 'a'))
print = logger.info
print('yo!')
答案 3 :(得分:4)
一个更简单的选项,
import logging, sys
logging.basicConfig(filename='path/to/logfile', level=logging.DEBUG)
logger = logging.getLogger()
sys.stderr.write = logger.error
sys.stdout.write = logger.info
答案 4 :(得分:2)
您真的应该这样做:通过调整您的日志记录配置以使用print
语句或其他方式,具体取决于设置。不要覆盖print
行为,因为将来可能会引入的某些设置(例如,您或其他人使用您的模块)实际上可能会将其输出到stdout
并且您将拥有问题。
有一个处理程序可以将您的日志消息重定向到正确的流(文件,stdout
或其他任何类似文件)。它被称为StreamHandler
,它与logging
模块捆绑在一起。
所以基本上我认为你应该这样做,你说过你不想做的事:用实际的日志记录替换print
语句。
答案 5 :(得分:1)
一旦定义了记录器,就可以使用它来使打印重定向到记录器,即使具有多个打印参数。
print = lambda *tup : logger.info(str(" ".join([str(x) for x in tup])))
答案 6 :(得分:0)
下面的内容在我的PySpark代码中非常完美。如果有人需要以防万一--
import os
import sys
import logging
import logging.handlers
log = logging.getLogger(__name_)
handler = logging.FileHandler("spam.log")
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
log.addHandler(handler)
sys.stderr.write = log.error
sys.stdout.write = log.info
(将在“ spam.log”中的每个错误记录在同一目录中,控制台/ stdout上将没有任何内容)
(将“ spam.log”中的所有信息记录在同一目录中,控制台/ stdout上将没有任何内容)
要在两个文件中以及控制台中打印输出错误/信息,请删除以上两行。
快乐编码 干杯!!!