【问题标题】:Python stderr - fail to parse exception messagePython stderr - 无法解析异常消息
【发布时间】:2013-09-12 14:01:40
【问题描述】:

我想解析异常打印,以便不会出现所有异常数据。

例如,我有以下异常消息:

Traceback(最近一次调用最后一次): 文件“C:\flow_development\console_debug_sample.py”,第 52 行,在 raise Exception('发生异常') 异常:发生异常

我想解析这个异常,只会出现异常消息:

异常发生

我用来编码的:

class Unbuffered:
    def __init__(self, stream):
        self.stream = stream
    def write(self, data):
        self.stream.write(data)
        self.stream.flush()
    def __getattr__(self, attr):
        return getattr(self.stream, attr)

if __name__ == "__main__":
    sys.stdout = Unbuffered(sys.stdout)
    sys.stderr = Unbuffered(sys.stderr)

    raise Exception('Exception occur')

但是,异常的每一行都分别调用了“write”函数,所以我无法刷新所有异常消息并进行解析。

有什么想法吗?

【问题讨论】:

  • 你到底为什么要这么做?你是否意识到你隐藏了很多有用的信息?事实上,如果你曾经提出关于 SO 的问题并且提供完整异常回溯,人们(包括我)询问你.所以,我希望你这样做只是因为你想试验异常处理,而不是真正的使用。

标签: python parsing exception flush


【解决方案1】:

您总是可以捕获异常。 如果您不想打印所有消息,只需捕获异常并打印您的消息。

例如。

import sys
class Unbuffered:
    def __init__(self, stream):
        self.stream = stream
    def write(self, data):
        self.stream.write(data)
        self.stream.flush()
    def __getattr__(self, attr):
        return getattr(self.stream, attr)

if __name__ == "__main__":
    try:
       sys.stdout = Unbuffered(sys.stdout)
       sys.stderr = Unbuffered(sys.stderr)

       raise Exception('Exception occur')
    except Exception:
       print 'Exception occur'

【讨论】:

    【解决方案2】:

    最简单的方法是更改​​sys.excepthook函数:

    import sys
    
    def my_hook(exc_type, exc_value, exc_tb):
        sys.stderr.write('{}: {}\n'.format(exc_type.__name__, exc_value))
        sys.stderr.flush()
        sys.exit(-1)
    
    
    sys.excepthook = my_hook
    

    在此更改之后,每当引发 未捕获 异常时,将不会打印回溯并且程序将退出:

    >>> raise RuntimeError('ARGHHH!!!')
    RuntimeError: ARGHHH!!!
    

    如果您想替换 sys.stderr 以执行此操作,那么您必须检查您是否正在打印回溯。例如:

    class NastyStderr(object):
        def __init__(self, stream):
            self.stream = stream
            self.printing_traceback = False
        def write(self, data):
            if self.printing_traceback:
                if not data.startswith('  '):
                    self.stream.write(data)
                    self.stream.flush()
                    self.printing_traceback = False
            else:
                if data.startswith('Traceback'):
                    self.printing_traceback = True
                elif not data.startswith('\nDuring handling'):
                    self.stream.write(data)
                    self.stream.flush()
        def __getattr__(self, attr):
            return getattr(self.stream, attr)
    

    用作:

    >>> sys.stderr = NastyStderr(sys.stderr)
    >>> raise ValueError('A')
    ValueError: A
    >>> try:
    ...     raise RuntimeError('A')
    ... except Exception as e:
    ...     raise ValueError('B')
    ... 
    RuntimeError: A
    ValueError: B
    

    正如您在第二个示例中看到的那样,它会打印发生的两个异常。编写一个能够理解它应该只打印第二个的NastyStderr 是相当困难的。

    但是,更改sys.excepthook 解决方案以打印回溯中的所有异常非常简单:

    >>> import sys
    >>> def my_hook(exc_type, exc_value, exc_tb, exit=True):
    ...     if exc_value.__context__ is not None:
    ...             prev = exc_value.__context__
    ...             my_hook(prev.__class__, prev, prev.__traceback__, exit=False)
    ...     sys.stderr.write('{}: {}\n'.format(exc_type.__name__, exc_value))
    ...     sys.stderr.flush()
    ...     if exit:
    ...             sys.exit(-1)
    ... 
    >>> sys.excepthook = my_hook
    >>> try:
    ...     raise Exception('A')
    ... except Exception:
    ...     raise ValueError('B')
    ... 
    Exception: A
    ValueError: B
    

    【讨论】:

    • 谢谢!!!!就像一个魅力:-) 我如何将 sys.excepthook 恢复为默认值?
    • @EitanG 有一个sys.__excepthook__ 参数可用于恢复默认值(与大多数其他属性一样)。
    • @EitanG 如果你觉得我的回答有用,你应该vote it up。如果它解决了你的问题,你应该accept the answer
    猜你喜欢
    • 1970-01-01
    • 2015-11-07
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多