Python:将 sys.stdout 和 sys.stderr 都捕获为日志文件
Python: capturing both of sys.stdout and sys.stderr as a log file
粗略地说,我想将其移植到纯 Python:
#!/bin/bash
{
python test.py
} &> /tmp/test.log
由于某些未知原因,这不起作用:
import os.path, sys
import tempfile
with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
sys.stdout = sys.stderr = fp
raise Exception("I'm dying")
当我使用 Python 2.6.6、Python 2.7.8 和Python CentOS 上的 3.4.2 x86_64.
但理想情况下,我想要 Python 2.6.
的解决方案
(目前,可以容忍将 stdout
和 stderr
或多线程的混合输出弄乱日志文件,只要任何数据不会简单地消失在黑洞中即可。)
显示一个简洁且可移植的解决方案,该解决方案已确认可与 sys.stderr
. 上的异常堆栈跟踪一起使用(最好是 os.dup2
以外的东西)
你可以使用这样的方法:
import traceback
import sys
from contextlib import contextmanager
@contextmanager
def output_to_file(filepath, write_mode='w'):
stdout_orig = None
stderr_orig = None
stdout_orig = sys.stdout
stderr_orig = sys.stderr
f = open(filepath, write_mode)
sys.stdout = f
sys.stderr = f
try:
yield
except:
info = sys.exc_info()
f.write('\n'.join(traceback.format_exception(*info)))
f.close()
sys.stdout = stdout_orig
sys.stderr = stderr_orig
用法是:
with output_to_file('test.log'):
print('hello')
raise Exception('I am dying')
并且 cat test.log
产生:
hello
Traceback (most recent call last):
File "<ipython-input-3-a3b702c7b741>", line 20, in outputi_to_file
yield
File "<ipython-input-4-f879d82580b2>", line 3, in <module>
raise Exception('I am dying')
Exception: I am dying
这对我有用:
#!/usr/bin/env python
from __future__ import print_function
import os, os.path, sys, tempfile
old_out = os.dup(sys.stdout.fileno())
old_err = os.dup(sys.stderr.fileno())
with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
fd = fp.fileno()
os.dup2(fd, sys.stdout.fileno())
os.dup2(fd, sys.stderr.fileno())
print("Testing")
print('testing errs', file=sys.stderr)
raise Exception("I'm dying")
future 只是为了更清晰地处理具有相同示例的 Python2 或 Python3。 (我还更改了 raise 语句以实例化异常,作为异常的字符串已被弃用很长时间并且它们在 Python3 下未得到适当支持)。 =11=]
如果我们想在使用重定向文件后恢复原始标准输出 and/or 标准错误,那么旧的_* 值就可以了。
记住文件对象在 with
块后关闭 :)
简单地使用这个:
sys.stdout = sys.stderr = open("test.log","w")
raise Exception("Dead")
退出后test.log的内容:
Traceback (most recent call last):
File "test.py", line 5, in <module>
raise Exception("Dead")
Exception: Dead
粗略地说,我想将其移植到纯 Python:
#!/bin/bash
{
python test.py
} &> /tmp/test.log
由于某些未知原因,这不起作用:
import os.path, sys
import tempfile
with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
sys.stdout = sys.stderr = fp
raise Exception("I'm dying")
当我使用 Python 2.6.6、Python 2.7.8 和Python CentOS 上的 3.4.2 x86_64.
但理想情况下,我想要 Python 2.6.
的解决方案(目前,可以容忍将 stdout
和 stderr
或多线程的混合输出弄乱日志文件,只要任何数据不会简单地消失在黑洞中即可。)
显示一个简洁且可移植的解决方案,该解决方案已确认可与 sys.stderr
. 上的异常堆栈跟踪一起使用(最好是 os.dup2
以外的东西)
你可以使用这样的方法:
import traceback
import sys
from contextlib import contextmanager
@contextmanager
def output_to_file(filepath, write_mode='w'):
stdout_orig = None
stderr_orig = None
stdout_orig = sys.stdout
stderr_orig = sys.stderr
f = open(filepath, write_mode)
sys.stdout = f
sys.stderr = f
try:
yield
except:
info = sys.exc_info()
f.write('\n'.join(traceback.format_exception(*info)))
f.close()
sys.stdout = stdout_orig
sys.stderr = stderr_orig
用法是:
with output_to_file('test.log'):
print('hello')
raise Exception('I am dying')
并且 cat test.log
产生:
hello
Traceback (most recent call last):
File "<ipython-input-3-a3b702c7b741>", line 20, in outputi_to_file
yield
File "<ipython-input-4-f879d82580b2>", line 3, in <module>
raise Exception('I am dying')
Exception: I am dying
这对我有用:
#!/usr/bin/env python
from __future__ import print_function
import os, os.path, sys, tempfile
old_out = os.dup(sys.stdout.fileno())
old_err = os.dup(sys.stderr.fileno())
with open(os.path.join(tempfile.gettempdir(), "test.log"), "a") as fp:
fd = fp.fileno()
os.dup2(fd, sys.stdout.fileno())
os.dup2(fd, sys.stderr.fileno())
print("Testing")
print('testing errs', file=sys.stderr)
raise Exception("I'm dying")
future 只是为了更清晰地处理具有相同示例的 Python2 或 Python3。 (我还更改了 raise 语句以实例化异常,作为异常的字符串已被弃用很长时间并且它们在 Python3 下未得到适当支持)。 =11=]
如果我们想在使用重定向文件后恢复原始标准输出 and/or 标准错误,那么旧的_* 值就可以了。
记住文件对象在 with
块后关闭 :)
简单地使用这个:
sys.stdout = sys.stderr = open("test.log","w")
raise Exception("Dead")
退出后test.log的内容:
Traceback (most recent call last):
File "test.py", line 5, in <module>
raise Exception("Dead")
Exception: Dead