【问题标题】:How to print an exception in Python?如何在 Python 中打印异常?
【发布时间】:2010-12-01 18:58:16
【问题描述】:
try:
    something here
except:
    print('the whatever error occurred.')

如何在我的except: 块中打印错误/异常?

【问题讨论】:

标签: python exception error-handling


【解决方案1】:

对于 Python 2.6 及更高版本以及 Python 3.x:

except Exception as e: print(e)

对于 Python 2.5 及更早版本,请使用:

except Exception,e: print str(e)

【讨论】:

  • str( KeyError('bad')) => 'bad' -- 不告诉异常类型
  • print(e) on keyerrors 似乎只给出了密钥,而不是完整的异常消息,这没什么帮助。
  • 如果要打印异常,最好使用print(repr(e));基本的Exception.__str__ 实现只返回异常消息,而不是类型。或者,使用traceback 模块,它具有打印当前异常、格式化或完整回溯的方法。
  • @MartijnPieters print(repr(e)) 没有给出任何跟踪。来自回溯模块的print_exc (在另一个答案中提到) 虽然在这种情况下有效。
  • @Hi-Angel:我在哪里声称打印repr(e) 会给出堆栈跟踪?我说的是str(e)repr(e) 之间的区别,后者包含更多信息,您还会在回溯的最后一行看到这些信息。我在评论中明确提到了traceback 模块。
【解决方案2】:

traceback 模块为formatting and printing exceptions 及其回溯提供方法,例如这将像默认处理程序一样打印异常:

import traceback

try:
    1/0
except Exception:
    traceback.print_exc()

输出:

Traceback (most recent call last):
  File "C:\scripts\divide_by_zero.py", line 4, in <module>
    1/0
ZeroDivisionError: division by zero

【讨论】:

  • 是否有某种 get_error_message 调用可以打印,因为我正在使用自己的打印例程添加一些其他内容。
  • @MikeSchem error_message = traceback.format_exc()
  • 这个截图不使用捕获的异常对象。您可以扩展代码以使用“前”吗? - 如except Exception as ex:...
  • @aaronsteers 它确实使用了捕获的异常;在异常处理程序中,当前异常可通过sys.exc_info() 函数获得,traceback.print_exc() 函数从那里获取它。只有在不处理异常或想要显示基于不同异常的信息时,您才需要显式传递异常。
  • 是的,我有时想保留异常并稍后打印它,当我不再处于“除外”块中时。
【解决方案3】:

Python 2.6 或更高版本中它更简洁:

except Exception as e: print(e)

在旧版本中它仍然可读:

except Exception, e: print e

【讨论】:

  • 在python3中,必须使用第一种方式,用“as”。
【解决方案4】:

如果您想传递错误字符串,这里有一个来自Errors and Exceptions (Python 2.6) 的示例

>>> try:
...    raise Exception('spam', 'eggs')
... except Exception as inst:
...    print type(inst)     # the exception instance
...    print inst.args      # arguments stored in .args
...    print inst           # __str__ allows args to printed directly
...    x, y = inst          # __getitem__ allows args to be unpacked directly
...    print 'x =', x
...    print 'y =', y
...
<type 'exceptions.Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

【讨论】:

    【解决方案5】:

    (我打算将此作为对@jldupont 答案的评论,但我没有足够的声誉。)

    我在其他地方也看到过类似@jldupont 的回答。 FWIW,我认为重要的是要注意这一点:

    except Exception as e:
        print(e)
    

    默认将错误输出打印到sys.stdout。一般来说,更合适的错误处理方法是:

    except Exception as e:
        print(e, file=sys.stderr)
    

    (请注意,您必须import sys 才能工作。)这样,错误将打印到STDERR 而不是STDOUT,这允许正确的输出解析/重定向/等。我知道这个问题严格来说是关于“打印错误”,但在这里指出最佳实践似乎很重要,而不是忽略这个可能导致最终无法更好地学习的人的非标准代码的细节。

    我没有像 Cat Plus Plus 的回答那样使用 traceback 模块,也许这是最好的方法,但我想我会把它扔在那里。

    【讨论】:

    • 我建议进一步添加flush=True。我注意到使用 systemd(并且没有使用适当的日志记录框架),在捕获到日志时缓冲不是我所期望的。
    【解决方案6】:

    Python 3:logging

    可以使用更灵活的logging 模块来记录异常,而不是使用基本的print() 函数。 logging 模块提供了很多额外的功能,例如将消息记录到给定的日志文件中,记录带有时间戳的消息以及有关记录发生位置的附加信息。 (更多信息请查看官方documentation。)

    可以使用模块级函数logging.exception() 记录异常,如下所示:

    import logging
    
    try:
        1/0
    except BaseException:
        logging.exception("An exception was thrown!")
    

    输出:

    ERROR:root:An exception was thrown!
    Traceback (most recent call last):
      File ".../Desktop/test.py", line 4, in <module>
        1/0
    ZeroDivisionError: division by zero 
    

    注意事项:

    • 函数logging.exception() 只能从异常处理程序中调用

    • 不应在日志处理程序中使用logging 模块以避免RecursionError(感谢@PrakharPandey)


    其他日志级别

    也可以通过使用关键字参数exc_info=True 以另一个日志级别记录异常,如下所示:

    logging.debug("An exception was thrown!", exc_info=True)
    logging.info("An exception was thrown!", exc_info=True)
    logging.warning("An exception was thrown!", exc_info=True)
    

    【讨论】:

    • 不应在日志处理程序中使用以避免 RecursionError
    【解决方案7】:

    在捕获异常时,人们几乎可以控制要显示/记录来自回溯的哪些信息。

    代码

    with open("not_existing_file.txt", 'r') as text:
        pass
    

    会产生以下回溯:

    Traceback (most recent call last):
      File "exception_checks.py", line 19, in <module>
        with open("not_existing_file.txt", 'r') as text:
    FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'
    

    打印/记录完整的回溯

    正如其他人已经提到的,您可以使用 traceback 模块捕获整个回溯:

    import traceback
    try:
        with open("not_existing_file.txt", 'r') as text:
            pass
    except Exception as exception:
        traceback.print_exc()
    

    这将产生以下输出:

    Traceback (most recent call last):
      File "exception_checks.py", line 19, in <module>
        with open("not_existing_file.txt", 'r') as text:
    FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'
    

    你可以通过使用日志来达到同样的目的:

    try:
        with open("not_existing_file.txt", 'r') as text:
            pass
    except Exception as exception:
        logger.error(exception, exc_info=True)
    

    输出:

    __main__: 2020-05-27 12:10:47-ERROR- [Errno 2] No such file or directory: 'not_existing_file.txt'
    Traceback (most recent call last):
      File "exception_checks.py", line 27, in <module>
        with open("not_existing_file.txt", 'r') as text:
    FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'
    

    仅打印/记录错误名称/消息

    您可能对整个回溯不感兴趣,而只对最重要的信息感兴趣,例如异常名称和异常消息,请使用:

    try:
        with open("not_existing_file.txt", 'r') as text:
            pass
    except Exception as exception:
        print("Exception: {}".format(type(exception).__name__))
        print("Exception message: {}".format(exception))
    

    输出:

    Exception: FileNotFoundError
    Exception message: [Errno 2] No such file or directory: 'not_existing_file.txt'
    

    【讨论】:

    • 希望我能多次支持这个答案,因为它比接受的答案更有帮助。
    • 在您的答案中的最后一部分(“仅打印/记录错误名称\消息”)如何仅使用 print 打印 ExceptionException Message 一次?每当我尝试这样做时,结果都很奇怪。
    • print(f"Exception: {type(exception).__name__}\nException message: {exception}")。开头的f 表示它是一个f-string,它只允许您将表达式放在花括号中,而不是使用.format()f-strings 仅适用于运行 Python 3.6+ 的系统
    【解决方案8】:

    在这里扩展“except Exception as e:”解决方案是一个不错的方法,其中包含一些附加信息,例如错误类型和发生位置。

    
    try:
        1/0
    except Exception as e:
        print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
    

    输出:

    ZeroDivisionError at line 48 of /Users/.../script.py: division by zero
    

    【讨论】:

      【解决方案9】:

      如果您想这样做,可以使用 assert 语句完成一个线性错误。这将帮助您编写可静态修复的代码并及早检查错误。

      assert type(A) is type(""), "requires a string"
      

      【讨论】:

        【解决方案10】:

        我建议使用 try-except 语句。此外,与使用打印语句不同,日志记录异常会在记录器上记录级别为 ERROR 的消息,我发现这比打印输出更有效。该方法只能从异常处理程序中调用,如下所示:

        import logging
        
        try:
            *code goes here*
        except BaseException:
            logging.exception("*Error goes here*")
        

        如果您想了解有关日志记录和调试的更多信息,this python page 上有很好的文档。

        【讨论】:

          猜你喜欢
          • 2017-05-26
          • 2017-12-21
          • 2020-10-18
          • 2013-02-24
          • 2016-01-19
          • 1970-01-01
          • 1970-01-01
          • 2014-01-02
          相关资源
          最近更新 更多