我在一个带有print语句的项目上有很多代码,想要快速编写这些print语句的脏记录器,并决定采用自定义路由。我设法将一个记录器打印到终端和文件(在这个站点的帮助下),但现在我想为每个语句添加一个简单的时间戳,我遇到了一个奇怪的问题。
这是我的日志记录类。
class Logger(object):
def __init__(self, stream):
self.terminal = stream
self.log = open("test.log", 'a')
def write(self, message):
self.terminal.flush()
self.terminal.write(self.stamp() + message)
self.log.write(self.stamp() + message)
def stamp(self):
d = datetime.today()
string = d.strftime("[%H:%M:%S] ")
return string
注意我在write方法中尝试使用的标记方法。
当运行以下两行时,我得到一个意外的输出:
sys.stdout = Logger(sys.stdout)
print("Hello World!")
输出:
[11:10:47] Hello World![11:10:47]
这也是输出在日志文件中看到的内容,但是,我看不出为什么我添加的字符串会附加到结尾。有人可以帮助我吗?
更新 见下面的答案。但是,为了更快地参考,问题是使用" print()"一般来说;在分配变量后用sys.stdout.write替换它。
还可以使用" logging"适用于长期/大型项目。
答案 0 :(得分:1)
它会调用您的流的.write()
方法两次,因为在cpython print
中调用了流.write()
方法两次。第一次是使用对象,第二次是写入换行符。例如,请查看line 138 in the pprint
module in cpython v3.5.2
def pprint(self, object):
self._format(object, self._stream, 0, 0, {}, 0)
self._stream.write("\n") # <- write() called again!
你可以测试一下:
>>> from my_logger import Logger # my_logger.py has your Logger class
>>> import sys
>>> sys.stdout = Logger(stream=sys.stdout)
>>> sys.stdout.write('hi\n')
[14:05:32] hi
您可以使用sed
替换代码中的print(<blah>)
。
$ for mymodule in *.py; do
> sed -i -E "s/print\((.+)\)/LOGGER.debug(\1)/" $mymodule
> done
结帐Python's Logging builtin module。它具有非常全面的日志记录,包括以所有消息格式包含时间戳。
import logging
FORMAT = '%(asctime)-15s %(message)s'
DATEFMT = '%Y-%m-%d %H:%M:%S'
logging.basicConfig(format=FORMAT, datefmt=DATEFMT)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.debug('message: %s', 'message')
这会将2016-07-29 11:44:20 message: message
输出到stdout
。还有处理程序将输出发送到文件。有一个basic tutorial,一个advanced tutorial和一个cookbook of common logging recipes。
有一个在食谱中使用simultaneous file and console loggers的例子。
import logging
LOGGER = logging.getLogger(__name__) # get logger named for this module
LOGGER.setLevel(logging.DEBUG) # set logger level to debug
# create formatter
LOG_DATEFMT = '%Y-%m-%d %H:%M:%S'
LOG_FORMAT = ('\n[%(levelname)s/%(name)s:%(lineno)d] %(asctime)s ' +
'(%(processName)s/%(threadName)s)\n> %(message)s')
FORMATTER = logging.Formatter(LOG_FORMAT, datefmt=LOG_DATEFMT)
CH = logging.StreamHandler() # create console handler
CH.setLevel(logging.DEBUG) # set handler level to debug
CH.setFormatter(FORMATTER) # add formatter to ch
LOGGER.addHandler(CH) # add console handler to logger
FH = logging.FileHandler('myapp.log') # create file handler
FH.setLevel(logging.DEBUG) # set handler level to debug
FH.setFormatter(FORMATTER) # add formatter to fh
LOGGER.addHandler(FH) # add file handler to logger
LOGGER.debug('test: %s', 'hi')
输出:
[DEBUG/__main__:22] 2016-07-29 12:20:45 (MainProcess/MainThread)
> test: hi
同时控制台和文件myapp.log
。
答案 1 :(得分:0)
您可能需要使用换行符。
class Logger(object):
def __init__(self, stream):
self.terminal = stream
self.log = open("test.log", 'a')
def write(self, message):
self.terminal.flush()
self.terminal.write(self.stamp() + message + "\n")
self.log.write(self.stamp() + message + "\n")
def stamp(self):
d = datetime.today()
string = d.strftime("[%H:%M:%S] ")
return string
无论如何,使用内置日志记录模块会更好。