在raiseerror和记录错误之间,在Python中哪一种做法更好?

在raiseerror和记录错误之间,在Python中哪一种做法更好?,python,Python,Python教程中有一个名为Errors和Exceptions的部分,它将结构用作 try: [statement] except [Built-in ExceptionType]: do something when an exception has been captured. finally: do something whether exception occurred or not. 这也可以通过直接引发错误来处理 try: raise [Built-

Python教程中有一个名为Errors和Exceptions的部分,它将结构用作

try:
    [statement]
except [Built-in ExceptionType]:
    do something when an exception has been captured.
finally:
    do something whether exception occurred or not.
这也可以通过直接引发错误来处理

try:
    raise [Built-in ExceptionType]
except [Built-in ExceptionType above] as e:
    print(f'foo error: {e}')
有几个内置的异常类型,好的实践是开发人员应该捕获开发人员应该查找的每个特定异常类型。(请参阅)

然而,在我阅读了日志部分之后。我想把错误记录到日志文件中,让用户意识到错误(可能只是打印文本,用户可以通知IT支持),而不是在屏幕上抛出异常。因此,我可以使用下面的错误消息并记录它,而不是上面的try/except组合

if len(symbol) != 1:
    error_message = f'Created box with symbol={symbol}, width={width} and height={height}, Symbol needs to be a string of length 1'
    logger.error(error_message)
    print(f'\nError! symbol={symbol}, width={width} and height={height} -- Symbol needs to be a string of length 1')
    return
我怀疑目前较好的做法是:

a) 在屏幕上引发错误,然后重试

b) 记录错误以便进一步调查

c) 其他方法(请建议我)

我希望我没有试图比较两种不同的东西。对我来说,我想选择b)并将错误存储在日志中。这便于调查,不会向用户提供不必要的信息。但我不确定我是否在正确的轨道上。非常感谢。

来自:

logging.handlers.SMTPHandler可用于发送记录的错误消息

    import logging
    import logging.handlers

    smtp_handler = logging.handlers.SMTPHandler(mailhost=("example.com", 25),
                                        fromaddr="from@example.com", 
                                        toaddrs="to@example.com",
                                        subject="Exception notification")
    logger = logging.getLogger()
    logger.addHandler(smtp_handler)
如果需要停止代码执行,可以在此处中断逻辑


再看看我前面提到的这个答案

你应该记录所有错误,不管它们是出于日志分析和重构等目的抛出或处理的

是否抛出或处理错误通常取决于代码的预期目的和错误的严重性

虽然“抛出”只能用于调试和处理 通过生产版本中的专用异常代码“优雅地” 应用程序没有用户喜欢崩溃。

  • 如果错误影响业务逻辑、代码的最终结果,或可能对软件用户造成损害,则您希望终止执行。您可以通过抛出错误或通过关闭程序的专用错误处理过程来处理它
  • 如果错误不严重且不影响程序的正常功能,则可以根据团队中的最佳实践和项目要求选择是处理错误还是抛出错误
      出于两种不同的目的,记录和引发异常是两件不同的事情。日志允许您检查程序在事后做了什么。引发异常现在对程序流有重要影响。有时候你想要一个,有时候你想要另一个,有时候你两者都想要

      问题总是在于错误是预期的还是意外的,是否有计划在发生错误时做什么,以及是否有必要通知任何人错误的发生


      应该捕获并处理您有“备份计划”的预期错误,这是常规程序控制流。意外错误可能会使程序停止,或者至少使发生错误的特定函数停止。如果上级调用方希望处理异常,请让他们处理。是否记录错误(除了处理或不处理错误外)取决于是否有人能从该日志条目中收集到有用的信息,或者它是否只是噪音。

      正如deceze已经提到的,记录和异常是两件完全不同的事情。一般来说:

      • 当遇到此时无法处理的意外/无效条件时,会引发异常。在这一点上,这个异常会发生什么(调用堆栈中是否有人会处理它)与您无关

      • 只有当您能够处理异常时,或者当您想记录异常时(最终需要附加上下文信息),才能捕获异常,然后重新激活它

      • 在应用程序的顶层,您最终会添加一个catchall异常处理程序,该处理程序可以记录异常,并根据应用程序的类型(命令行脚本、GUI应用程序、Web服务器等)决定处理这种情况的最佳方法

      日志记录主要是用于事后检查、程序行为分析等的开发人员/管理工具,它既不是错误处理工具,也不是最终用户UI功能。你的例子是:

      if len(symbol) != 1:
          error_message = f'Created box with symbol={symbol}, width={width} and height={height}, Symbol needs to be a string of length 1'
          logger.error(error_message)
          print(f'\nError! symbol={symbol}, width={width} and height={height} -- Symbol needs to be a string of length 1')
          return
      

      是一个完美的反模式。如果函数需要一个字符串,而调用方传递了其他任何内容,那么唯一合理的解决方案是引发异常并让调用方处理它。它是如何运行的,再一次与您无关。

      如果您使用的是django,那么它内置了异常通知,我看不到django在这里被标记。无论如何,这取决于形势。如果程序在捕捉到此类错误后不应运行,则应引发异常。如果没有,就记录下来。如果程序在后台以非交互方式运行,则必须进行日志记录。如果程序在捕捉到某个错误后停止运行,则始终可以抛出异常,并将其记录在该错误之上,以供将来参考/调查。
      if len(symbol) != 1:
          error_message = f'Created box with symbol={symbol}, width={width} and height={height}, Symbol needs to be a string of length 1'
          logger.error(error_message)
          print(f'\nError! symbol={symbol}, width={width} and height={height} -- Symbol needs to be a string of length 1')
          return