使用Python将stdout和stderr重定向到同一个文件

9
我想将Python脚本的标准错误和标准输出重定向到同一个输出文件。从终端中,我可以使用以下命令:
$ python myfile.py &> out.txt

为了完成我想要的同样的任务,但需要从Python脚本本身完成。我查看了这些问题:将子进程的stderr重定向到stdout如何重定向Python中的stderr?以及这里的示例10.10,然后我尝试了以下内容:
import sys
fsock = open('out.txt', 'w')
sys.stdout = sys.stderr = fsock

print "a"

正确地将字母“a”打印到out.txt文件中;然而,当我尝试以下操作时:

import sys
fsock = open('out.txt', 'w')
sys.stdout = sys.stderr = fsock

print "a   # missing end quote, will give error

我在终端中收到了“SyntaxError …”的错误提示,但在out.txt文件中没有收到。我该怎么做才能将SyntaxError发送到out.txt文件中呢?我不想写一个异常处理,因为那样会在脚本中写入太多的异常。我正在使用Python 2.7。
更新:如下面的答案和评论所指出的,SyntaxError将始终输出到屏幕上,我将以下一行代码替换为:
print "a   # missing end quote, will give error

by

print 1/0  # Zero division error

"

ZeroDivisionError被输出到文件中,因为我希望在我的问题中有这个错误。

"

尝试在您的代码中引发一个不是语法错误的错误。在 print "a" 之后,引发一个类似于 raise ValueError('A very specific bad thing happened') 的错误。 - James Russo
@JamesRusso,我宁愿不引发任何异常,因为我在问题中已经提到了原因。有没有一种方法可以从Python脚本内部模拟“&>文件名”的bash方式? - gora
我只是在提到为了测试目的... 为了测试它是否正常工作,只需引发一个错误并确保它被写入您的文件。如果是这样,所有未来的错误都应该被写入文件。 - James Russo
@jsbueno和James Russo,看起来问题出在SyntaxError上。可能其他异常被重定向到文件中了,就像我想要的那样。 - gora
@jsbueno 这在Python 3.6中不起作用吗?我正在尝试类似的代码,但是文本文件中没有任何内容被打印出来。 - Moondra
2个回答

11
这个有效。
sys.stdout = open('out.log', 'w')
sys.stderr = sys.stdout

2
我确认它可以工作。我尝试了除以零的操作,并在同一个日志文件中得到了回溯和“ZeroDivisionError:division by zero”,同时stdout也被打开。我正在使用Python 3.7.1。 - Le Droid

3
在像上面这样的Python文件中出现SyntaxError时,在程序开始运行之前就会被触发: Python文件与任何其他编译语言一样被编译 - 如果解析器或编译器无法在Python文件中找到意义,就不会生成可执行字节码,因此程序也不会运行。
在代码中有意生成异常的正确方法 - 从像您的简单测试用例到实现复杂流程控制模式,都是使用Python命令raise
只需保留打印,并在末尾添加类似于这样的行:
raise Exception

那么你就能看到你的技巧是有效的。

如果没有明确的raise,你的程序在运行时可能会以许多其他方式失败,例如,如果你强制除以0,或者只是尝试使用未分配(因此“未声明”)的变量 - 但是故意的SyntaxError将产生这样的影响:程序根本不会开始运行,甚至连前几行也不会执行。


我在脚本末尾加入了“raise Exception”语句,但仍然输出到屏幕。我特别注意到SyntaxError的问题。在我的实际脚本中,问题很可能不是语法错误,而是数字错误。无论如何,我都希望将错误发送到文件中。 - gora
好的 - 我刚刚使用了您的确切模式,它对我有效。当然,如果这是一个未捕获的异常,会在字符串上打印东西,这也意味着程序在那一点上终止。但是异常回溯会写入文件。 - jsbueno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接