python异常值如何处理_如何处理异常
python異常值如何處理
最近,我與一個朋友進行了討論,他是一個相對初級但很聰明的軟件開發人員。 她問我有關異常處理的問題。 這些問題指出了一種技巧和竅門,肯定有它們的清單。 但是我堅信我們編寫軟件的方式背后的背景和動機,因此我決定從這樣一個角度寫關于異常的想法。
編程中的異常(使用Java作為故事的舞臺)用于通知我們在執行代碼期間發生了問題。 異常是類的特殊類別。 使它們與眾不同的是,它們擴展了Exception類,而后者又擴展了Throwable類。 作為Throwable的實現,我們可以在必要時“拋出”它們。 那么,如何發生異常? 使用throw語句從JVM或代碼段中引發異常類的實例。 那是怎么回事,但是為什么呢?
我敢肯定,當我們看到異常發生時,我們大多數人都會畏縮,但它們是我們受益的工具。 在引發異常之前,返回了特殊值或錯誤代碼,以使我們知道操作沒有成功。 忘記(或不知道)檢查此類錯誤代碼,可能會導致我們的應用程序發生不可預測的行為。 所以對
在我撰寫以上內容時,我想到了兩件事。 異常是一個不好的事件,因為創建異常時我們知道發生了問題。 異常是一種有用的構造,因為異??梢詾槲覀兲峁┯嘘P發生錯誤的有價值的信息,并允許我們針對每種情況采取適當的行為。試圖散布此設計問題的實質: 觸發方法/請求執行某項操作,但它可能會失敗–我們如何最好地通知調用方它失敗了? 我們如何傳達有關發生的情況的信息? 我們如何幫助客戶決定下一步該怎么做? 使用異常的問題在于我們“放棄了”,而不僅僅是“放棄”。 我們以“爆炸性”的方式來做,我們服務的客戶/呼叫者必須處理混亂 。
因此,關于異常是我的第一條建議,因為它們是一件壞事,請盡量避免 。 在您所控制的軟件部分中,實施難以出錯的設計。 您可以使用支持此行為的語言功能。 我相信Java中最常見的異常是NullPointerException,而Optionals可以幫助我們避免它們。 讓我們考慮一下我們想要檢索具有指定id的雇員:
public Optional<Employee> tryGetEmployee(String employeeId) {return Optional.ofNullable(employeeService.getEmployee(employeeId)); }現在好多了。 但是,除了我們語言的功能之外,我們還可以通過某種方式設計代碼,以免發生錯誤。 如果我們考慮一種只能接收正整數作為輸入的方法,則可以設置代碼,這樣客戶端錯誤地傳遞無效輸入的可能性就很小。 首先,我們創建一個PositiveInteger類:
public class PositiveInteger {private Integer integerValue;public PositiveInteger(Integer inputValue) {if(inputValue <= 0) {throw new IllegalArgumentException("PositiveInteger instances can only be created out of positive integers");}this.integerValue = inputValue;}public Integer getIntegerValue() {return integerValue;} }然后,對于只能使用正整數作為輸入的方法:
public void setNumberOfWinners(PositiveInteger numberOfWinners) { … } 這些當然是簡單的例子,我確實認為,問題的核心是偶爾出現問題,然后我們必須告知客戶發生的情況。 假設我們從外部后端系統檢索了一個員工列表,那么事情可能會出錯。 如何處理呢?
我們可以將響應對象設置為GetEmployeesResponse,如下所示:
但是,讓我們成為現實主義者,您無法控制代碼庫的每個部分,也不會更改所有內容。 確實會發生異常,因此,讓我們從它們的簡要背景信息開始。
如前所述,Exception類擴展了Throwable類。 所有異常都是異常類的子類。 可以將異常分為已檢查和未檢查的異常。 這僅表示某些異常(已檢查的異常)要求我們在編譯時指定在異常發生時應用程序的行為方式。 未檢查的異常不要求我們進行編譯時間處理。 要創建此類異常,您可以擴展RuntimeException類,該類是Exception的直接子類。 關于已檢查與未檢查的較舊的常見指導原則是,運行時異常用于表示應用程序通常無法預期或從中恢復的情況,而已檢查異常是編寫良好的應用程序應從中預期并從中恢復的情況。
好吧,我主張僅使用運行時異常 。 而且,如果我使用的庫具有帶檢查異常的方法,則我將創建一個包裝器方法,將其轉換為運行時。 那為什么不檢查異常呢? Bob叔叔在他的“ Clean Code”一書中指出, 它們違反了Open / Closed原理 ,因為使用新的throws聲明更改簽名可能會對調用該方法的程序的許多級別產生影響。
現在,無論是檢查還是未檢查,由于異常是一種結構,可讓我們洞悉出了什么問題,因此應該對所發生的事情盡可能地具體和豐富 。 因此, 嘗試使用標準異常,其他人將更容易理解發生的情況。 看到NullPointerException時,任何人都清楚原因。 如果您自己設置例外,請使其明智且具體。 例如,ValidationException使我知道某個驗證失敗,AgeValidationException將我指向特定的驗證失敗。 具體而言,既可以更容易地診斷出發生了什么,又可以根據發生的事情(異常類型)指定不同的行為。 這就是為什么您必須始終首先捕獲最具體的異常的原因! 因此,這里出現了另一個常見建議,指示不要抓住“異常”。 這是一個有效的建議,我偶爾不遵循。 在我的api的邊界(比如說我的REST服務的端點)中,我總是有通用的catch Exception子句。 我不希望任何意外以及我在代碼中無法預測或防止的某些事情可能會向外界揭示事物。
具有描述性,但也可以根據抽象級別提供例外 。 考慮創建一個異常層次結構,以不同的抽象級別提供語義信息。 如果從程序的較低層引發了異常,例如與數據庫相關的異常,則不必向API的調用者提供詳細信息。 捕獲異常并引發一個更抽象的異常,該異常僅通知調用者其嘗試的操作失敗。 這似乎與“僅在可能的情況下才捕獲”的常見方法背道而馳,但事實并非如此。 只是在這種情況下,我們的“處理”是觸發新異常。 在這些情況下,通過將原始異常傳遞給新異常的構造函數,可以使整個異常歷史在拋出之間可用。
“手柄”一詞已被多次使用。 這是什么意思? 當異常在我們熟悉的catch子句中被“捕獲”時,被視為已處理。 引發異常時,首先它將在發生異常的代碼中搜索異常處理,如果找不到異常,它將進入所包含方法的調用上下文,依此類推,直到找到異常處理程序或程序為止將終止。
我再次喜歡Bob叔叔的一件好事,就是try-catch-finally塊定義了程序中的作用域。 除詞匯范圍外,我們還應考慮其概念范圍,將try塊視為事務 。 如果出問題了該怎么辦? 我們如何確保使程序保持有效狀態? 不要忽略例外! 我猜程序員對許多小時的不滿是由無聲異常引起的。 捕獲并最終阻止是您進行清理的地方。 確保等待,直到掌握了正確處理異常的所有信息為止。 這可以與早起早發的原則聯系在一起。 我們提早拋出,因此我們不必進行由于異常而不得不稍后恢復的操作,而為了及時掌握所有信息以正確處理異常,我們不必遲到。 順便說一句,當您捕獲異常時,只有在解決它們時才記錄日志,否則單個異常事件會導致日志混亂。 最后,對于異常處理,我個人更喜歡創建一個可以在代碼的不同部分中使用的錯誤處理服務 ,并在日志記錄,重新拋出,清理資源等方面采取適當的措施。它集中了我的錯誤處理行為,避免了代碼重復,并幫助我從更高級的角度了解應用程序中如何處理錯誤。
現在我們有了足夠的上下文,悖論,規則及其例外,我們可以總結一下:
- 盡量避免例外。 使用語言功能和適當的設計來實現它
- 使用運行時異常,將方法與檢查的異常包裝在一起,然后將其轉換為運行時
- 嘗試使用標準異常
- 使您的例外情況具有特定性和描述性
- 首先捕獲最具體的異常
- 不要趕上異常
- 但是請在您的API邊界上抓住Exception。 完全掌控一切
- 創建與應用程序的層和功能匹配的異常層次結構
- 在適當的抽象級別上拋出異常。 逐層移動時,捕獲異常并引發更高級別的異常
- 通過在新的構造函數中提供異常,在重新拋出時傳遞完整的異常歷史記錄
- 將try-catch-finally塊視為事務。 當出現問題時,請確保將程序保持在有效狀態
- 在可以處理時捕獲異常
- 永遠不要有空的catch子句
- 處理異常時記錄異常
- 擁有全局異常處理服務,并具有如何處理錯誤的策略
就是這樣! 繼續,要與眾不同!
翻譯自: https://www.javacodegeeks.com/2017/12/how-to-deal-with-exceptions.html
python異常值如何處理
總結
以上是生活随笔為你收集整理的python异常值如何处理_如何处理异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win10系统怎样打开PST格式文件(怎
- 下一篇: glacier2_Amazon Glac