2012-02-17 103 views
1

當我調用與系統庫(如shutil,http等)交互的代碼時,如果系統處於意外狀態(例如,文件鎖定,網絡不可用等)僅捕獲Python運行時錯誤

try: 
    # call something 
except: 
    print("OK, so it went wrong.") 

這困擾我,因爲它還捕捉基於編程錯誤SyntaxError和其他異常,我見過的建議,以避免這種開放式的異常處理程序。

是否有一個約定,所有的運行時錯誤都來自一些常見的異常基類,我可以在這裏使用?或者任何不涉及語法錯誤,模塊導入失敗等的東西?即使KeyError我會考慮一個bug,因爲我傾向於使用dict.get(),如果我不是100%確定密鑰將在那裏。

我不願意列出每一個可以想象的異常類型,特別是因爲我打電話給我很多支持代碼,我無法控制。

UPDATE: OK,問題的答案使我意識到我問錯了問題 - 我真正想知道的,如果有一個Python約定或明確的建議,爲圖書館的作家使用特定的基類的例外,以便將它們從更普通的朋友中分離出來。

因爲如果有一個圖書館編寫者的約定,我作爲一個圖書館消費者,可以對可能拋出什麼做出一般假設,即使具體情況可能會有所不同。不知道這是否更有意義?

再次更新:埃裏克森的回答最終讓我明白,而不是放棄和追趕在頂層的一切,我可以處理,並在較低的水平細化異常,因此頂層只需要擔心來自下面的級別的特定異常類型。

謝謝!

+0

謝謝,我已經搜查,但沒有設法清除一個明確的答案。解析/語法/程序員錯誤和運行時錯誤之間的區別在哪裏? – 2012-02-17 15:29:59

+0

請注意,您通常不會捕獲一個'SyntaxError' - 在編譯*源代碼時,很久以後它就會被拋出。如果你的'try'塊包含'import','exec','execfile()'或者'eval()',那麼'SyntaxError'唯一可以被捕獲。 – 2012-02-17 15:47:04

+0

@SvenMarnach:呵呵,我確定我看過這些無類型的處理程序能夠捕捉到甚至語法錯誤,但它可能是其他的東西,更微妙。我沒有一個簡單的例子。感謝您的更正。 – 2012-02-17 15:51:38

回答

6
  1. 始終使try塊越小越好。

  2. 只捕捉你想處理的異常。查看你正在處理的功能的文檔。

這可確保您考慮可能發生的異常情況,並考慮發生異常情況時的處理方法。如果發生了什麼事情,你從來沒有想過,反正你的異常處理代碼無法正確處理這種情況,所以它最好傳播異常。

你說你不願意列出每一種可能的異常類型,但通常情況並非如此。打開文件?捕獲IOError。處理一些庫代碼?他們通常擁有自己的異常層次結構,並帶有特定的頂級異常 - 如果要捕獲任何特定於庫的異常,只需抓住此異常層級即可。儘可能具體,否則錯誤遲早會被忽視。

至於關於Python中用戶定義的異常的約定:他們usually should be derived from Exception。這也是什麼標準庫大多數用戶定義的異常從派生,所以你應該做的最少的是使用

except Exception: 

代替裸except條款,這也捕捉KeyboardInterruptSystemExit的。正如你已經注意到的那樣,這仍然會捕捉到許多你不想捕捉的異常。

+0

這是非常好的建議。 – aculich 2012-02-18 04:15:11

+0

謝謝賢者的忠告!我認爲'Exception'會讓我陷入像OverflowError這樣的問題,我認爲這也是程序員錯誤。但是關於特定於庫的異常的注意事項讓我想到了 - 如果我能夠連接所有內部模塊來拋出特定於lib的異常,這將更容易處理。對於我已經完成的模塊,錯誤處理要簡單得多。 – 2012-02-18 07:52:31

1

如何RuntimeErrorhttp://docs.python.org/library/exceptions.html#exceptions.RuntimeError

如果這不是你想要的(而且很可能不是),看看該網頁上的例外列表中。如果您對層次結構的組合方式感到困惑,我建議您花十分鐘檢查您感興趣的例外的屬性,以查看它們共享的基類。 (請注意,__bases__未在整個層次結構中關閉 - 您可能還需要檢查超類基礎)。

+1

「這個例外主要是來自以前版本的解釋器的遺留物,它不再被使用太多。」 – kindall 2012-02-17 15:29:25

+0

@kindall:鏈接頁面包含所有內置的異常,因此OP可以選擇他喜歡的內容,正如你所知道的。 – Marcin 2012-02-17 15:31:31

+0

我知道RuntimeError,但我還沒有找到一個明確的建議,庫作家使用它作爲所有運行時錯誤的基礎......是否有這樣的事情? – 2012-02-17 15:31:32

5

在Python文檔中查看built-in exceptions的列表。這聽起來像你最想要的是趕上StandardError,雖然這也包括KeyError。還有其他基類,例如ArithmeticErrorEnvironmentError,有時您可能會覺得有用。

我發現第三方庫確實從Exception派生自己的自定義例外,如此處所述。在適當的情況下,程序員也傾向於提出標準的Python異常,例如TypeError,ValueError等。不幸的是,這使得難以一致地將庫錯誤與Exception派生的其他錯誤分開。我希望Python定義一個UserException基類。有些庫會爲它們的異常聲明一個基類,但是你必須知道它們是什麼,導入模塊並明確地捕獲它們。

當然,如果你想趕上一切除了KeyError,並說,IndexError,用腳本,塞例外一起,你可以這樣做:

try: 
    doitnow() 
except (StopIteration, GeneratorExit, KeyboardInterrupt, SystemExit): 
    raise # these stop the script 
except (KeyError, IndexError): 
    raise # we don't want to handle these ones 
except Exception as e: 
    handleError(e) 

誠然,這將成爲一個麻煩事每次寫入。

+0

不錯,我沒有想到明確地捕捉並重新提出我/不想/想要捕捉的東西。 – 2012-02-17 15:37:30

+0

「我希望Python定義例如UserException基類。」 - 這也是我所希望的。對於Python來說這似乎是非典型的,它對於約定通常很強大。 – 2012-02-17 15:43:52