在 Python 中使用 with 语句时,将 stderr 和 stdout 重定向到文件不会写入错误

Redirecting stderr and stdout to a file does not write errors when using with statements in Python

我有一个程序可以将输出和错误重定向到一个日志文件,这样我就可以在它自动运行时查看它。它工作正常,直到我从使用 open()close() 方法切换到使用 with 语句。

我的原文是:

import sys
log = open("log.txt", "w", encoding="utf-8")
sys.stdout = sys.stderr = log
print("hello world")
print(1 / 0)
print("goodbye world")
log.close()

它输出了我预期的结果:

hello world
Traceback (most recent call last):
  File "testing.py", line 5, in <module>
    print(1 / 0)
ZeroDivisionError: division by zero

但是当我把它改成:

import sys
with open("log.txt", "w", encoding="utf-8") as log:
    sys.stdout = sys.stderr = log
    print("hello world")
    print(1 / 0)
    print("goodbye world")

文件只显示:

hello world

我不熟悉这两种方法之间的区别(除了第二种方法更容易阅读)所以我的问题是:为什么 with 语句无法记录错误并且有没有办法在保留 with 语句的同时记录错误?

发生这种情况是因为 with 语句由于发生异常而在写入错误输出之前关闭了资源。 看看 docs.

The following code:

with EXPRESSION as TARGET:
    SUITE

is semantically equivalent to:

manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False

try:
    TARGET = value
    SUITE
except:
    hit_except = True
    if not exit(manager, *sys.exc_info()):
        raise
finally:
    if not hit_except:
        exit(manager, None, None, None)

第一种情况处理异常的原因是因为资源在python退出时关闭,而不是因为关闭语句。