2017-07-18 129 views
-1

這是這樣的慣用/ pythonic做還是有更好的方法嗎?我希望所有錯誤都能在日誌中記錄,以防萬一我無法訪問控制檯輸出。此外,我想中止這種代碼路徑,以防出現問題。日誌記錄剛剛出現異常

try: 
     with open(self._file_path, "wb") as out_f: 
      out_f.write(...) 
      ... 
    except OSError as e: 
     log("Saving %s failed: %s" % (self._file_path, str(e))) 
     raise 

編輯:這個問題是關於在正確的地方處理異常/正確的成語。這不是關於logging類。

+0

[使用日誌python類寫入文件?](https://stackoverflow.com/questions/6386698/using-the-logging-python-class-to-write-toa-a-文件) –

+0

更新了問題 – VladimirLenin

+0

我並不真的在這裏得到降低票數和結束選票。就我而言,這是一個非常明智的問題,而且絕對不是「基於意見」。 –

回答

1

一個經過驗證的工作方案是在應用程序代碼的頂層有一個通用的except子句,以確保任何未處理的錯誤都會被記錄下來(並且會重新提出) - 同時它還使您有機會嘗試並在崩潰之前進行一些清理)

一旦你有了這個,在你的代碼中添加特定的「日誌和重新刷新」異常處理程序是有意義的,如果你想在日誌消息中捕獲更多的上下文信息,如您的片段示例。這意味着異常可能會最終記錄兩次,但這很難,也是問題。

如果你真的是Python的(或者,如果你珍惜你的錯誤日誌),使用stdlib's logging module和它的logger.exception()方法,將自動地完整回溯添加到日誌。

日誌記錄模塊的一些(其他)好處是能夠從日誌記錄調用中解耦日誌記錄配置(應該由應用程序本身處理,並且可以非常細化)(這通常發生在庫代碼級別),與編寫良好的庫的兼容性(已經使用logging,因此您只需配置記錄器即可從第三方庫獲取信息 - 這實際上可以節省您的屁股),並且可以使用不同的日誌記錄機制(根據日誌源和嚴重性以及部署環境,將stderr,將文件,syslog,通過電子郵件警報發送給任何人,而且不限於單個處理程序)。

更新:

你會說什麼再提高相同的異常(如實例),或者重新提高自定義異常(MyLibException),而不是原單?

這確實是一個常見的模式,但矯枉過正,要小心 - 你只需要針對實際預期異常,在那裏你真的知道事業做到這一點。一些異常類可能有不同的原因 - 比如OSError,'IOError and RuntimeError - so never assume anything about what really caused the exception, either check it with a decently robust condition (for example the .errno field for IOError`)或讓異常傳播。我曾經浪費了幾個小時試圖理解爲什麼一些lib在錯誤的輸入文件中抱怨,當真正的原因是權限問題時(我發現它跟蹤了庫代碼...)。

這種模式的另一個可能的問題是(至少在Python2中)你將失去原來的異常和回溯,所以最好在引發你自己的異常之前正確記錄它們。 IIRC Python3有一些機制可以以更簡潔的方式處理這種情況,讓您保留一些原始的異常信息。

+0

感謝您的詳細回覆。關於重新提出相同的異常(如示例中)或重新提升自定義異常(MyLibException)而不是原始異常,您會說些什麼?第二種選擇讓我能夠縮小可能出現的例外情況,這些例外情況是由我的圖書館故意產生的。它還可以區分圖書館已知的錯誤。 – VladimirLenin

+0

@VladimirLenin比較我編輯的答案。 –