Python 的異常機制及規範是否相當不人性化?

  1. python的標準庫中都眾所周知各種隨處隨手的 raise,遑論各種質量參差的第三方庫?
  2. python的官方 PEP8 標準中卻又明確要求

When catching exceptions, mention specific exception

這分明是霸王條款一般的語言規範,如果要客戶做到 catch specific exception,那麼至少你的語言層面要有 raise specific exception 的機制吧(類似 java?),然而 python 並沒有。

實在有些令人哭笑不得。


你們啊,不要想喜歡弄個大新聞。拿Java來黑Python前別忘了你家語言里也有unchecked exception。

原文明明是這樣的:

When catching exceptions, mention specific exceptions whenever possible instead of using a bare except: clause.

這意思太明確了:

  1. 如果可能的話,盡量捕捉更specific的exception
  2. 而不是用except:來捕捉所有異常。

你要明白PEP8不是強制標準。即使它是強制的,except Exception:也足夠滿足這個條款,不知道題主『哭笑不得』在哭啥笑啥。

原因需要結合PEP8里關於Exception的部分:

Derive exceptions from

Exception

rather than

BaseException

從BaseException繼承的exception中,最常見的就是KeyboardInterrupt了。如果你的代碼里用except:來捕捉異常,會導致長時間執行的代碼無法用ctrl+c來終止。

一個代碼良好的library,應該會自己定義一個base的exception class(比如說FooException),然後再從這個exception繼承更詳細的exception(比如說IlligalFooException)。這樣你的代碼使用的時候可以except FooException捕捉這個library的所有可能異常,也可以用except IlligalFooException來捕捉更詳細的異常。

如果你用的library不是以這樣的形式定義異常,而是直接重用 6. Built-in Exceptions,建議直接扔掉。


你先舉個隨手raise的例子吧


題主的意思應該希望Python有Java一樣的checked exception,也就是在函數體上寫明可拋異常種類,甚至可以做編譯檢查,而不是像現在一樣,只能查文檔和看源代碼。

但是Python這種動態語言本來在編譯時就沒多少檢查,不僅不告訴你能拋什麼異常,連參數和返回值可以是什麼類型都沒有,為什麼單獨揪著沒有exception specification來說呢?Python的風格就是一切運行時再決定,不爽不要用。


@yegle 大嬸回答的,excited!

恰好上周重構一個小程序的時候,搜了一些異常處理相關資料,羅列一下:

0. Robust exception handling

嗯。這篇博文中首先就提到了 LBYLEAFP 這兩種錯誤處理模式,還提到 Exceptions vs. error status codes 之間的抉擇。

1. Write Cleaner Python: Use Exceptions

這篇博文講的是如何通過合理地利用 Python 異常機制編寫更清晰的 Python 的代碼

這篇博文還提到,在 Python 中,異常無處不在,所以不要覺得到處 raise 就不好了。畢竟,即使有未處理異常,程序也不至於像 C++ 中那樣直接 terminated 了。

2. Re-raising Exceptions

這篇提到,以 raise 為目的的 try...except:/try...except Exception: 不是耍流氓:

try:
...
except: # except Exception:
...
raise # excited!

最後,一些標準模塊處理異常的思路也值得學習。比如,想避免:

try:
...
except: # except Exception:
...

可以考慮這樣:

class MyError(Exception): pass
try:
...
except MyError:
...

嗯。ftplib.Error 就是一個的例子。


看優秀的庫, werkzeug/exceptions.py at master · mitsuhiko/werkzeug · GitHub

全憑自覺


推薦閱讀:

Go 語言的錯誤處理機制是一個優秀的設計嗎?
各種編程語言中的「錯誤/異常處理」有哪些成熟的,優雅的或是熱門的機制/思想?
為什麼C++中,析構函數、operator delete、以及operator delete []按照慣例不會拋出異常?
c++ 程序運行時異常處理,怎麼定位到出錯代碼行?
如何優雅的處理(或忽略)c++函數返回值代表的錯誤?

TAG:Python | 異常處理 |