在下面的代碼中,我本希望將例外輸出和回溯寫入test.txt檔案,但這并沒有發生。
import contextlib
with open("test.txt", "a") as f:
with contextlib.redirect_stderr(f):
raise Exception("Hello")
為什么它沒有按預期作業,如何正確地將例外輸出重定向到檔案?
uj5u.com熱心網友回復:
因為重定向sys.stderr不會在 python 中捕獲例外(如果這樣做會很糟糕,對吧?因為例外只能被try/except塊捕獲。)所以例外處理代碼會中斷您正在運行的代碼(和重定向)。
證明:
import contextlib
from sys import stderr
with open("test.txt", "a") as f:
with contextlib.redirect_stderr(f):
sys.stderr.write("hello")
sys.stderr.flush()
寫正確。
要將所有例外的輸出重定向到檔案,您有兩個選擇:在try/except塊中全域捕獲所有例外并自己撰寫,或者使用 shell 重定向將腳本的stderr發送到檔案,例如
python my_script.py 2>errors.txt
如果您想自己做,請參閱此問題以討論獲取回溯。
uj5u.com熱心網友回復:
只是為了添加我選擇的替代實作。
以下是將例外輸出重定向到記錄器。在我的例子中,記錄器被設定為標準輸出(默認),所以我曾經contextlib.redirect_stdout將記錄器的輸出重定向到一個檔案,但你當然可以直接讓記錄器寫入一個檔案。
import logging
import contextlib
from typing import Iterator
@contextlib.contextmanager
def capture_exception(logger: logging.Logger) -> Iterator[None]:
"""
Captures exceptions and redirects output to the logger
>>> import logging
>>> logger = logging.getLogger()
>>> with capture_exception(logger=logger):
>>> raise Exception("This should be outputed to the logger")
"""
try:
# try/except block where exception is captured and logged
try:
yield None
except Exception as e:
logger.exception(e)
finally:
pass
用法:
logger = logging.getLogger() # default should be stdout
with open("test.txt", "a") as f:
with contextlib.redirect_stdout(f), capture_exception(logger):
# ^-- multiple context managers in one `with` statement
raise Exception("The output of this exception will appear in the log. Great success.")
出現在日志中的例外輸出:
The output of this exception will appear in the log. Great success.
Traceback (most recent call last):
File "/tmp/ipykernel_9802/2529855525.py", line 52, in capture_exception
yield None
File "/tmp/ipykernel_9802/3344146337.py", line 9, in <module>
raise Exception("The output of this exception will appear in the log. Great success.")
Exception: The output of this exception will appear in the log. Great success.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/324125.html
上一篇:如何使用縮進拋出例外?
下一篇:嘗試使日期疼痛時,laravel中的Carbon\Exceptions\InvalidFormatException問題
