繁体   English   中英

在引发错误和记录错误之间,在Python中哪种更好的做法?

[英]Between raise Error and logging the Error, which one is a better practice in Python?

Python教程有一个名为“错误和异常”的小节,该节使用以下结构:

try:
    [statement]
except [Built-in ExceptionType]:
    do something when an exception has been captured.
finally:
    do something whether exception occurred or not.

这也可以通过直接引发Error来处理。

try:
    raise [Built-in ExceptionType]
except [Built-in ExceptionType above] as e:
    print(f'foo error: {e}')

有几种内置的ExceptionType,优良作法是开发人员应捕获开发人员应查找的每种特定的异常类型。 (请参阅为什么“除外:通过”是一种不好的编程习惯?

但是,在我阅读了日志记录部分之后。 我正在考虑将错误记录到日志文件中,并让用户知道该错误(也许只是打印文本,并且用户可以通知IT支持),而不是在屏幕上抛出异常。 因此,除了上面的组合以外,我可以使用以下错误消息并将其记录下来,而不是尝试/。

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)并将错误存储在日志中。 这更易于调查,并且不会向用户提供不必要的信息。 但我不确定我是否走对了。 非常感谢你。

记录和引发异常出于两个不同目的的两个不同事物。 日志使您可以检查事实之后程序的操作。 提高例外,现在对程序流程有重要影响。 有时您想要一个,有时您想要另一个,有时您想要两者。

问题始终是错误是预期的还是意外的,您是否有计划计划万一发生错误,以及将错误的发生通知任何人是否有用。

应该捕获并处理您具有“备份计划”的预期错误,即常规程序控制流。 意外错误可能会终止程序,或者至少终止发生它们的特定功能。 如果较高的呼叫者希望处理异常,请让他们处理。 是否记录错误(除了处理还是不处理错误)取决于是否有人可以从该日志条目中收集任何有用的见解,或者仅仅是杂讯。

应该记录所有错误,无论是出于日志分析和重构目的而抛出还是处理它们。

引发还是处理错误通常取决于代码的预期目的和错误的严重性。

尽管“抛出”仅应在调试中使用,并在应用程序的生产版本中由专用异常代码“优美地”处理。 没有用户喜欢崩溃。

  • 如果错误影响业务逻辑,代码的最终结果,或可能导致软件用户的损失 ,则您想终止执行。 您可以通过引发错误或通过关闭程序的专用错误处理过程来处理它。
  • 如果错误不是很严重并且不会影响程序的正常功能,则可以根据团队中的最佳实践和项目要求来选择是处理还是抛出该错误。

正如deceze已经提到的,日志记录和异常是两个完全不同的东西。 作为基本规则:

  • 当遇到意外的/无效的条件时,您将引发异常,此时无法处理代码。 此时,您不必担心该异常的结果(无论调用堆栈中的某个人是否会处理)

  • 您只有在可以处理或想要记录异常时才捕获异常(最终带有附加的上下文信息),然后重新引发

  • 在您的应用程序的顶层,您最终添加了一个万能的异常处理程序,该处理程序可以记录异常并根据应用程序的类型(命令行脚本,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

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

文档中

Returns a new instance of the SMTPHandler class. The instance is initialized with the from and to addresses and subject line of the email. The toaddrs should be a list of strings. 

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)

如果需要停止执行代码,则可以在此处破坏逻辑。

也环顾这个答案,我已经提到了之前的collat​​e-output-in-python-logging-memoryhandler-with-smtphandler

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM