Python 的異常機制及規範是否相當不人性化?
- python的標準庫中都眾所周知各種隨處隨手的 raise,遑論各種質量參差的第三方庫?
- 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.
這意思太明確了:
- 如果可能的話,盡量捕捉更specific的exception
- 而不是用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嗯。這篇博文中首先就提到了 LBYL 和 EAFP 這兩種錯誤處理模式,還提到 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++函數返回值代表的錯誤?