簡體   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