[英]Redirect all stdout/stderr globally to logger
I have a very large python application that launches command-line utilities to get pieces of data it needs. 我有一个非常大的python应用程序,它启动命令行实用程序来获取所需的数据。 I currently just redirect the python launcher script to a log file, which gives me all of the
print()
output, plus the output of the command-line utilities, ie: 我目前只是将python启动程序脚本重定向到一个日志文件,它给了我所有的
print()
输出,以及命令行实用程序的输出,即:
python -m launcher.py &> /root/out.log
I've since implemented a proper logger via logging
, which lets me format the logging statements more precisely, lets me limit log file size, etc. I've swapped out most of my print()
statements with calls to my logger. 我已经通过
logging
实现了一个合适的记录器,这使我可以更精确地格式化日志记录语句,让我限制日志文件大小等。我已经通过调用我的记录器来换掉大部分的print()
语句。 However, I have a problem: none of the output from the command-line applications is appearing in my log. 但是,我遇到了一个问题:命令行应用程序的输出都没有出现在我的日志中。 It instead gets dumped to the console.
它反而被转储到控制台。 Also, the programs aren't all launched the same way: some are launched via
popen()
, some by exec()
, some by os.system()
, etc. 此外,程序并非都以相同的方式启动:一些通过
popen()
启动,一些通过exec()
,一些通过os.system()
。
Is there a way to globally redirect all stdout
/ stderr
text to my logging function, without having to re-write/modify the code that launches these command-line tools? 有没有办法将所有
stdout
/ stderr
文本全局重定向到我的日志记录功能,而无需重新编写/修改启动这些命令行工具的代码? I tried setting setting the following which I found in another question: 我尝试设置以下我在另一个问题中找到的设置:
sys.stderr.write = lambda s: logger.error(s)
However it fails with " sys.stderr.write
is read-only". 但它失败了“
sys.stderr.write
是只读的”。
While this is not a full answer, it may show you a redirect to adapt to your particular case. 虽然这不是一个完整的答案,但它可能会向您显示重定向以适应您的特定情况。 This is how I did it a while back.
这是我一段时间做的。 Although I cannot remember why I did it this way, or what the limitation was I was trying to circumvent, the following is redirecting
stdout
and stderr
to a class for print()
statements. 虽然我不记得为什么我这样做了,或者我试图规避的限制是什么,以下是将
stdout
和stderr
重定向到print()
语句的类。 The class subsequently writes to screen and to file: 该类随后写入屏幕和文件:
import os
import sys
import datetime
class DebugLogger():
def __init__(self, filename):
timestamp = datetime.datetime.strftime(datetime.datetime.utcnow(),
'%Y-%m-%d-%H-%M-%S-%f')
#build up full path to filename
logfile = os.path.join(os.path.dirname(sys.executable),
filename + timestamp)
self.terminal = sys.stdout
self.log = open(logfile, 'a')
def write(self, message):
timestamp = datetime.datetime.strftime(datetime.datetime.utcnow(),
' %Y-%m-%d-%H:%M:%S.%f')
#write to screen
self.terminal.write(message)
#write to file
self.log.write(timestamp + ' - ' + message)
self.flush()
def flush(self):
self.terminal.flush()
self.log.flush()
os.fsync(self.log.fileno())
def close(self):
self.log.close()
def main(debug = False):
if debug:
filename = 'blabla'
sys.stdout = DebugLogger(filename)
sys.stderr = sys.stdout
print('test')
if __name__ == '__main__':
main(debug = True)
import sys
import io
class MyStream(io.IOBase):
def write(self, s):
logger.error(s)
sys.stderr = MyStream()
print('This is an error', stream=sys.stderr)
This make all call to sys.stderr
go to the logger. 这使得对
sys.stderr
所有调用都转到了记录器。 The original one is always in sys.__stderr__
原始的一个总是在
sys.__stderr__
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.