http://blog.csdn.net/pipisorry/article/details/21841883html
斷言是一句必須等價於布爾真的斷定;此外,發生異常也意味着表達式爲假.這些工做相似於 C 語言預處理器中 assert 宏,但在 Python 中它們在運行時構建(與之相對的是編譯期判別).
若是你剛剛接觸斷言這個概念,無妨.斷言能夠簡簡單單的想象爲 raise-if 語句(更準確的說是raise-if-not 語句).測試一個表達式,若是返回值是假,觸發異常.python
斷言語句等價於這樣的 Python 表達式,若是斷言成功不採起任何措施(相似語句),不然觸發AssertionError(斷言錯誤)的異常.assert 的語法以下:
assert expression[, arguments]數據庫
示例assert mode in ["train", "eval", "inference"],若是輸入的mode不在其中則觸發異常express
[Python中什麼時候使用斷言]編程
最重要的問題是你在開發過程當中隱藏了bug,若是當時你沒加這個Try…Catch,恐怕你早就發現這個bug了,由於程序壓根就跑不下去。segmentfault
[try catch 對代碼運行的性能影響]socket
(含py2和py3的區別)函數
Python 3
try:性能
...
except Exception as e:
print(e)
不過lz推薦下面的格式:
import traceback
try:
...
except:
print(traceback.format_exc())
input("hold on...")
直接調用print Exception, e獲得的結果就只有一行信息,只是異常的名字和說明而已。而這樣能夠輸出棧信息,ide中點擊就能夠到達錯誤位置,而且不會一閃而過。
1)因此異常都從 BaseException繼承,並刪除了StardardError 。StandardError
異常:在Python 2裏,StandardError
是除了StopIteration
,GeneratorExit
,KeyboardInterrupt
,SystemExit
以外全部其餘內置異常的基類。在Python 3裏,StandardError
已經被取消了;使用Exception
替代。
Notes | Python 2 | Python 3 |
---|---|---|
x =StandardError() |
x =Exception() |
|
x =StandardError(a, b, c) |
x =Exception(a, b, c) |
2)去除了異常類的序列行爲和.message屬性
3)異常鏈,由於__context__在3.0a1版本中沒有實現
as
。as
也能夠用在一次捕獲多種類型異常的狀況下。在導入模塊(或者其餘大多數狀況)的時候,你絕對不該該使用這種方法(指以上的fallback)。否則的話,程序可能會捕獲到像KeyboardInterrupt
(若是用戶按Ctrl-C來中斷程序)這樣的異常,從而使調試變得更加困難。
Python 3裏,拋出自定義異常的語法有細微的變化。
Notes | Python 2 | Python 3 |
---|---|---|
① | raise MyException |
unchanged |
② | raise MyException,'error message' |
raise MyException('error message') |
③ | raise MyException,'error message', a_traceback |
raise MyException('error message').with_traceback(a_traceback) |
④ | raise 'error message' |
unsupported |
Note:
2to3
將會警告你它不能自動修復這種語法。How can I write a lambda expression that's equivalent to:
def x():
raise Exception()
The following is not allowed:
y = lambda : raise Exception()
lambda errmsg: exec('raise(Exception(errmsg))')
[Define a lambda expression that raises an Exception]
在Python 2裏,生成器有一個throw()
方法。調用a_generator.throw()
會在生成器被暫停的時候拋出一個異常,而後返回由生成器函數獲取的下一個值。在Python 3裏,這種功能仍然可用,可是語法上有一點不一樣。
Notes | Python 2 | Python 3 |
---|---|---|
① | a_generator.throw(MyException) |
no change |
② | a_generator.throw(MyException,'error message') |
a_generator.throw(MyException('error message')) |
③ | a_generator.throw('error message') |
unsupported |
2to3
會顯示一個警告信息,告訴你須要手動地來修復這處代碼。Python 3中的異常處理也發生了一點變化。在Python 3中必須使用「as」關鍵字。
Python 2
try:
let_us_cause_a_NameError
except NameError, err:
print err, '--> our error message'
name 'let_us_cause_a_NameError' is not defined --> our error message
Python 3
try:
let_us_cause_a_NameError
except NameError as err:
print(err, '--> our error message')
name 'let_us_cause_a_NameError' is not defined --> our error message
except的一個例子:
考慮下面這個文件
import sys def bar(i): if i == 1: raise KeyError(1) def bad(): e = None try: bar(int(sys.argv[1])) except KeyError as e: print('key error') print(e) bad()
在python2中一切運做正常
$ python foo.py 1
key error 1
可是在python3中事情變得一團糟
$ python3 foo.py 1
key error
Traceback (most recent call last):
File "foo.py", line 19, in <module> bad() File "foo.py", line 17, in bad print(e) UnboundLocalError: local variable 'e' referenced before assignment
Note:問題出在,在Python3中,異常對象沒法在異常塊做用域外訪問。(緣由是在垃圾收集器運行且從內存中清理引用以前會在內存棧幀中保存一個引用週期)
解決此問題的方法之一是在異常塊做用域外圍護一個異常對象的引用,以使其可訪問。這裏是前例使用這一技術的一個版本,使得代碼對Python2和Python3都友好:
import sys
def bar(i): if i == 1: raise KeyError(1) def good(): exception = None try: bar(int(sys.argv[1])) except KeyError as e: exception = e print('key error') print(exception)
如今除以變量A=0都不會被try-except捕捉到了,會直接在運行時警告:
RuntimeWarning: divide by zero encountered in double_scalars
只有直接除以0纔會被try-except捕捉到
x,y爲字典,若是x < y的不能比較,拋出TypeError異常。2.x版本是返回僞隨機布爾值的。
處理異常的時候,在sys模塊裏有三個你能夠訪問的變量:sys.exc_type,sys.exc_value,sys.exc_traceback。(實際上這些在Python 1的時代就有。)從Python 1.5開始,因爲新出的sys.exc_info,再也不推薦使用這三個變量了,這是一個包含全部以上三個元素的元組。在Python 3裏,這三個變量終於再也不存在了;這意味着,你必須使用sys.exc_info。
Notes | Python 2 | Python 3 |
---|---|---|
sys.exc_type | sys.exc_info()[0] | |
sys.exc_value | sys.exc_info()[1] | |
sys.exc_traceback | sys.exc_info()[2] |
[python上下文管理器ContextLib及with語句]
在異常處理語句中,當try代碼塊沒有拋出任何的異常時,else語句塊會被執行到。
def my_to_int(str_param):
try:
print int(str_param)
except ValueError:
print 'cannot convert {} to a integer'.format(str_param)
else:
print 'convert {} to integer successfully'.format(str_param)
my_to_int("123")
my_to_int("me123")
convert 123 to integer successfully
cannot convert me123 to a integer
如打印日誌所示,在轉換成功未發生錯的的時候,else語句裏的邏輯會被執行,固然這個例子可能並無什麼太多的實際的用處,但大體能說明else在錯誤處理中的用處:簡化邏輯,避免使用一些標誌值就可以準確把握是否發生錯誤的狀況來作一些實際的操做(好比在保存數據的時候若是發生錯誤,在else語句塊中進行rollback的操做,而後緊接着還能加上finally語句完成一些清理操做。
Exceptions做爲一種控制結構,在處理數據庫、sockets、文件或者任何可能失敗的資源時很是經常使用。使用標準的 try 、except 結構寫數據庫操做時一般是類型這樣的方式。
try:
# get API data
data = db.find(id='foo') # may raise exception
# manipulate the data
db.add(data)
# save it again
db.commit() # may raise exception
except Exception:
# log the failure
db.rollback()
db.close()
你能發現這裏的問題嗎?這裏有兩種可能的異常會觸發相同的except模塊。這意味着查找數據失敗(或者爲查詢數據創建鏈接失敗)會引起回退操做。這絕對不是咱們想要的,由於在這個時間點上事務並無開始。一樣回退也不該該是數據庫鏈接失敗的正確響應,所以讓咱們將不一樣的狀況分開處理。
首先,咱們將處理查詢數據。
try:
# get API data
data = db.find(id='foo') # may raise exception
except Exception:
# log the failure and bail out
log.warn("Could not retrieve FOO")
return
# manipulate the data
db.add(data)
如今數據檢索擁有本身的try-except,這樣當咱們沒有取得數據時,咱們能夠採起任何處理方式。沒有數據咱們的代碼不大可能再作有用的事,所以咱們將僅僅退出函數。除了退出你也能夠構造一個默認對象,從新進行檢索或者結束整個程序。
如今讓咱們將commit的代碼也單獨包起來,這樣它也能更優雅的進行錯誤處理。
try:
db.commit() # may raise exception
except Exception:
log.warn("Failure committing transaction, rolling back")
db.rollback()
else:
log.info("Saved the new FOO")
finally:
db.close()
實際上,咱們已經增長了兩端代碼。首先,讓咱們看看else,當沒有異常發生時會執行這裏的代碼。在咱們的例子中,這裏只是將事務成功的信息寫入日誌,可是你能夠按照須要進行更多有趣的操做。一種可能的應用是啓動後臺任務或者通知。
很明顯finally 子句在這裏的做用是保證db.close() 老是可以運行。回顧一下,咱們能夠看到全部和數據存儲相關的代碼最終都在相同的縮進級別中造成了漂亮的邏輯分組。之後須要進行代碼維護時,將很直觀的看出這幾行代碼都是用於完成 commit操做的。
常見的python異常類型
from:http://blog.csdn.net/pipisorry/article/details/21841883