[英]Custom logger with time stamp in python
I have lots of code on a project with print statements and wanted to make a quick a dirty logger of these print statements and decided to go the custom route. 我在一个带有打印语句的项目中有很多代码,想要快速创建这些打印语句的肮脏记录器,并决定采用自定义路线。 I managed to put together a logger that prints both to the terminal and to a file (with the help of this site), but now I want to add a simple time stamp to each statement and I am running into a weird issue.
我设法将一个记录器打印到终端和文件上(在此站点的帮助下),但是现在我想为每个语句添加一个简单的时间戳,并且遇到了一个奇怪的问题。
Here is my logging class. 这是我的测井课程。
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
Notice the stamp method that I then attempt to use in the write method. 请注意然后尝试在write方法中使用的stamp方法。
When running the following two lines I get an unexpected output: 运行以下两行时,我得到意外的输出:
sys.stdout = Logger(sys.stdout)
print("Hello World!")
Output: 输出:
[11:10:47] Hello World![11:10:47]
This what the output also looks in the log file, however, I see no reason why the string that I am adding appends to the end. 这也是输出在日志文件中显示的内容,但是,我看不出我要添加的字符串附加到末尾的原因。 Can someone help me here?
有人可以帮我吗?
UPDATE See answer below. 更新请参见下面的答案。 However, for quicker reference the issue is using "print()" in general;
但是,为了便于参考,该问题通常使用“ print()”。 replace it with sys.stdout.write after assigning the variable.
分配变量后,将其替换为sys.stdout.write。
Also use "logging" for long-term/larger projects right off the bat. 对于长期/较大的项目,也请立即使用“日志记录”。
It calls the .write()
method of your stream twice because in cpython print
calls the stream .write()
method twice. 它调用
.write()
你流的方法两次,因为在CPython的print
调用流.write()
方法的两倍。 The first time is with the object, and the second time it writes a newline character. 第一次与对象在一起,第二次它与对象写入换行符。 For example look at line 138 in the
pprint
module in cpython v3.5.2 例如,查看cpython v3.5.2中
pprint
模块中的第138行
def pprint(self, object):
self._format(object, self._stream, 0, 0, {}, 0)
self._stream.write("\n") # <- write() called again!
You can test this out: 您可以测试一下:
>>> 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
You can replace print(<blah>)
everywhere in your code using sed
. 您可以使用
sed
在代码中的任何地方替换print(<blah>)
。
$ for mymodule in *.py; do
> sed -i -E "s/print\((.+)\)/LOGGER.debug(\1)/" $mymodule
> done
Check out Python's Logging builtin module . 查看Python的Logging内置模块 。 It has pretty comprehensive logging including inclusion of a timestamp in all messages format.
它具有非常全面的日志记录,包括以所有消息格式包含时间戳。
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')
This outputs 2016-07-29 11:44:20 message: message
to stdout
. 这将输出
2016-07-29 11:44:20 message: message
到stdout
。 There are also handlers to send output to files. 还有一些处理程序可以将输出发送到文件。 There is a basic tutorial , an advanced tutorial and a cookbook of common logging recipes .
有一个基本的教程 ,一个高级的教程和一个常用的日志记录食谱 。
There is an example of using simultaneous file and console loggers in the cookbook. 食谱中有一个同时使用文件和控制台记录器的示例。
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')
This outputs: 输出:
[DEBUG/__main__:22] 2016-07-29 12:20:45 (MainProcess/MainThread)
> test: hi
to both console and file myapp.log
simultaneously. 同时访问控制台和文件
myapp.log
。
You probably need to use newline character. 您可能需要使用换行符。
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
Anyway, using built-in logging module will be better. 无论如何,使用内置的日志记录模块会更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.