且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

redirect_stderr 不起作用(Python 3.5)

更新时间:2023-10-23 11:56:28

你需要真正写入 stderr,它不是捕捉异常的工具.

>>>从 contextlib 导入 redirect_stderr>>>导入 io>>>f = io.StringIO()>>>导入系统>>>使用 redirect_stderr(f):...打印('你好',文件= sys.stderr)...>>>f.seek(0)0>>>f.read()'你好\n'

要捕获异常,您需要做更多的工作.您可以使用日志库(外部),或编写自己的异常处理程序,然后使用您的自定义输出.

这里有一些快速的东西,它使用一个记录器实例来帮助写入流:

log = logging.getLogger('TEST')log.addHandler(logging.StreamHandler(stream=f))def exception_handler(exc_type, exc_value, exc_traceback):如果是子类(exc_type,KeyboardInterrupt):# 让系统处理诸如CTRL+C之类的事情sys.__excepthook__(*args)log.error('异常:', exc_info=(exc_type, exc_value, exc_traceback))sys.excepthook = 异常处理程序引发运行时错误('foo')

这里的 f 是与上面相同的 StringIO 实例.运行此代码后,您不应在控制台上看到任何回溯,但它会存储在流对象中:

>>>f.seek(0)0>>>打印(f.read())你好例外:回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中运行时错误:foo

#! python3
from contextlib import redirect_stderr
import io

f = io.StringIO()
with redirect_stderr(f):
    # simulates an error
    erd

As seen above, I have used the redirect_stderr function to redirect stderr to a StringIO object. However, it doesn't work, as the error message is still printed out in command prompt:

Traceback (most recent call last):
  File "C:\Users\max\testerr.py", line 8, in <module>
    erd
NameError: name 'erd' is not defined

I tested it on Python 3.5.1 64 bit and 3.5.2 64 bit with the same results.

A similar issue in this thread

I have also tried writing the error to a file as described in the linked thread, but the file is empty after running the script.

You need to actually write to stderr, it is not a tool to catch exceptions.

>>> from contextlib import redirect_stderr
>>> import io
>>> f = io.StringIO()
>>> import sys
>>> with redirect_stderr(f):
...    print('Hello', file=sys.stderr)
...
>>> f.seek(0)
0
>>> f.read()
'Hello\n'

To catch exceptions, you need to do some more work. You can use a logging library (external), or write your own exception handler, and then use your custom output for it.

Here is something quick, which uses a logger instance to help write to the stream:

log = logging.getLogger('TEST')
log.addHandler(logging.StreamHandler(stream=f))

def exception_handler(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
       # Let the system handle things like CTRL+C
       sys.__excepthook__(*args)
    log.error('Exception: ', exc_info=(exc_type, exc_value, exc_traceback))

sys.excepthook = exception_handler
raise RuntimeError('foo')

Here f is the same StringIO instance from above. After you run this code, you should not see any traceback on your console, but it will be stored in the stream object:

>>> f.seek(0)
0
>>> print(f.read())
Hello
Exception:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: foo