A. python錯誤類型
Python程序開發中的錯誤通常可分為三類:語法錯誤、運行時錯誤和邏輯錯誤。
1.語法錯誤,語法錯誤是在Python程序開發中最常見的錯誤,如關鍵字輸入錯誤、變數未賦值使用、函數未定義等。在一些Python集成開發環境(如PyCharm)中,輸入程序代碼時會自動檢測語法錯誤,並且錯誤位置以紅色波浪線標出。因此,此類錯誤比較容易被發現和改正。
2.運行時錯誤,運行時錯誤是指Python代碼編譯通過,在運行代碼時發生的錯誤。這類錯誤往往是由指令代碼執行了非法操作引起的,如數組下標越界、除數為0、試圖打開一個不存在的文件、連接資料庫錯誤等。當程序中出現這種錯誤時,程序會自動中斷,並給出有關的錯誤信息提示。
3.邏輯錯誤,程序運行結果和預期結果不一致,說明程序中存在邏輯錯誤,如運算符使用不正確,語句順序不對,循環語句的起始值、終值或步長設置不對等。邏輯錯誤通常不會產生錯誤提示,只能根據運行結果知道程序中出現了錯誤。因此,這種錯誤較難被排除,需要編程人員仔細閱讀代碼,使用調試和排錯技巧,在可疑代碼處插入斷點並逐句跟蹤,檢查相關變數的值等方法,分析錯誤位置和原因。
B. 我執行一段python腳本報錯了,怎麼解決
在程序運行的過程中,如果發生了錯誤,可以事先約定返回一個錯誤代碼,這樣,就可以知道是否有錯,以及出錯的原因。在操作系統提供的調用中,返回錯誤碼非常常見。比如打開文件的函數open(),成功時返迴文件描述符(就是一個整數),出錯時返回-1。
用錯誤碼來表示是否出錯十分不便,因為函數本身應該返回的正常結果和錯誤碼混在一起,造成調用者必須用大量的代碼來判斷是否出錯:
復制代碼代碼如下:
def foo():
r = some_function()
if r==(-1):
return (-1)
# do something
return r
def bar():
r = foo()
if r==(-1):
print 'Error'
else:
pass
一旦出錯,還要一級一級上報,直到某個函數可以處理該錯誤(比如,給用戶輸出一個錯誤信息)。
所以高級語言通常都內置了一套try...except...finally...的錯誤處理機制,Python也不例外。
try
讓我們用一個例子來看看try的機制:
復制代碼代碼如下:
try:
print 'try...'
r = 10 / 0
print 'result:', r
except ZeroDivisionError, e:
print 'except:', e
finally:
print 'finally...'
print 'END'
當我們認為某些代碼可能會出錯時,就可以用try來運行這段代碼,如果執行出錯,則後續代碼不會繼續執行,而是直接跳轉至錯誤處理代碼,即except語句塊,執行完except後,如果有finally語句塊,則執行finally語句塊,至此,執行完畢。
上面的代碼在計算10 / 0時會產生一個除法運算錯誤:
復制代碼代碼如下:
try...
except: integer division or molo by zero
finally...
END
從輸出可以看到,當錯誤發生時,後續語句print 'result:', r不會被執行,except由於捕獲到ZeroDivisionError,因此被執行。最後,finally語句被執行。然後,程序繼續按照流程往下走。
如果把除數0改成2,則執行結果如下:
復制代碼代碼如下:
try...
result: 5
finally...
END
由於沒有錯誤發生,所以except語句塊不會被執行,但是finally如果有,則一定會被執行(可以沒有finally語句)。
你還可以猜測,錯誤應該有很多種類,如果發生了不同類型的錯誤,應該由不同的except語句塊處理。沒錯,可以有多個except來捕獲不同類型的錯誤:
復制代碼代碼如下:
try:
print 'try...'
r = 10 / int('a')
print 'result:', r
except ValueError, e:
print 'ValueError:', e
except ZeroDivisionError, e:
print 'ZeroDivisionError:', e
finally:
print 'finally...'
print 'END'
int()函數可能會拋出ValueError,所以我們用一個except捕獲ValueError,用另一個except捕獲ZeroDivisionError。
此外,如果沒有錯誤發生,可以在except語句塊後面加一個else,當沒有錯誤發生時,會自動執行else語句:
復制代碼代碼如下:
try:
print 'try...'
r = 10 / int('a')
print 'result:', r
except ValueError, e:
print 'ValueError:', e
except ZeroDivisionError, e:
print 'ZeroDivisionError:', e
else:
print 'no error!'
finally:
print 'finally...'
print 'END'
Python的錯誤其實也是class,所有的錯誤類型都繼承自BaseException,所以在使用except時需要注意的是,它不但捕獲該類型的錯誤,還把其子類也「一網打盡」。比如:
復制代碼代碼如下:
try:
foo()
except StandardError, e:
print 'StandardError'
except ValueError, e:
print 'ValueError'
第二個except永遠也捕獲不到ValueError,因為ValueError是StandardError的子類,如果有,也被第一個except給捕獲了。
Python所有的錯誤都是從BaseException類派生的
使用try...except捕獲錯誤還有一個巨大的好處,就是可以跨越多層調用,比如函數main()調用foo(),foo()調用bar(),結果bar()出錯了,這時,只要main()捕獲到了,就可以處理:
復制代碼代碼如下:
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except StandardError, e:
print 'Error!'
finally:
print 'finally...'
也就是說,不需要在每個可能出錯的地方去捕獲錯誤,只要在合適的層次去捕獲錯誤就可以了。這樣一來,就大大減少了寫try...except...finally的麻煩。
調用堆棧
如果錯誤沒有被捕獲,它就會一直往上拋,最後被Python解釋器捕獲,列印一個錯誤信息,然後程序退出。來看看err.py:
復制代碼代碼如下:
# err.py:
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('0')
main()
執行,結果如下:
復制代碼代碼如下:
$ python err.py
Traceback (most recent call last):
File "err.py", line 11, in <mole>
main()
File "err.py", line 9, in main
bar('0')
File "err.py", line 6, in bar
return foo(s) * 2
File "err.py", line 3, in foo
return 10 / int(s)
ZeroDivisionError: integer division or molo by zero
出錯並不可怕,可怕的是不知道哪裡出錯了。解讀錯誤信息是定位錯誤的關鍵。我們從上往下可以看到整個錯誤的調用函數鏈:
錯誤信息第1行:
復制代碼代碼如下:
Traceback (most recent call last):
告訴我們這是錯誤的跟蹤信息。
第2行:
復制代碼代碼如下:
File "err.py", line 11, in <mole>
main()
調用main()出錯了,在代碼文件err.py的第11行代碼,但原因是第9行:
復制代碼代碼如下:
File "err.py", line 9, in main
bar('0')
調用bar('0')出錯了,在代碼文件err.py的第9行代碼,但原因是第6行:
復制代碼代碼如下:
File "err.py", line 6, in bar
return foo(s) * 2
原因是return foo(s) * 2這個語句出錯了,但這還不是最終原因,繼續往下看:
復制代碼代碼如下:
File "err.py", line 3, in foo
return 10 / int(s)
原因是return 10 / int(s)這個語句出錯了,這是錯誤產生的源頭,因為下面列印了:
復制代碼代碼如下:
ZeroDivisionError: integer division or molo by zero
根據錯誤類型ZeroDivisionError,我們判斷,int(s)本身並沒有出錯,但是int(s)返回0,在計算10 / 0時出錯,至此,找到錯誤源頭。
記錄錯誤
如果不捕獲錯誤,自然可以讓Python解釋器來列印出錯誤堆棧,但程序也被結束了。既然我們能捕獲錯誤,就可以把錯誤堆棧列印出來,然後分析錯誤原因,同時,讓程序繼續執行下去。
Python內置的logging模塊可以非常容易地記錄錯誤信息:
復制代碼代碼如下:
# err.py
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except StandardError, e:
logging.exception(e)
main()
print 'END'
同樣是出錯,但程序列印完錯誤信息後會繼續執行,並正常退出:
復制代碼代碼如下:
$ python err.py
ERROR:root:integer division or molo by zero
Traceback (most recent call last):
File "err.py", line 12, in main
bar('0')
File "err.py", line 8, in bar
return foo(s) * 2
File "err.py", line 5, in foo
return 10 / int(s)
ZeroDivisionError: integer division or molo by zero
END
通過配置,logging還可以把錯誤記錄到日誌文件里,方便事後排查。
拋出錯誤
因為錯誤是class,捕獲一個錯誤就是捕獲到該class的一個實例。因此,錯誤並不是憑空產生的,而是有意創建並拋出的。Python的內置函數會拋出很多類型的錯誤,我們自己編寫的函數也可以拋出錯誤。
如果要拋出錯誤,首先根據需要,可以定義一個錯誤的class,選擇好繼承關系,然後,用raise語句拋出一個錯誤的實例:
復制代碼代碼如下:
# err.py
class FooError(StandardError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
執行,可以最後跟蹤到我們自己定義的錯誤:
復制代碼代碼如下:
$ python err.py
Traceback (most recent call last):
...
__main__.FooError: invalid value: 0
只有在必要的時候才定義我們自己的錯誤類型。如果可以選擇Python已有的內置的錯誤類型(比如ValueError,TypeError),盡量使用Python內置的錯誤類型。
最後,我們來看另一種錯誤處理的方式:
復制代碼代碼如下:
# err.py
def foo(s):
n = int(s)
return 10 / n
def bar(s):
try:
return foo(s) * 2
except StandardError, e:
print 'Error!'
raise
def main():
bar('0')
main()
在bar()函數中,我們明明已經捕獲了錯誤,但是,列印一個Error!後,又把錯誤通過raise語句拋出去了,這不有病么?
其實這種錯誤處理方式不但沒病,而且相當常見。捕獲錯誤目的只是記錄一下,便於後續追蹤。但是,由於當前函數不知道應該怎麼處理該錯誤,所以,最恰當的方式是繼續往上拋,讓頂層調用者去處理。
raise語句如果不帶參數,就會把當前錯誤原樣拋出。此外,在except中raise一個Error,還可以把一種類型的錯誤轉化成另一種類型:
復制代碼代碼如下:
try:
10 / 0
except ZeroDivisionError:
raise ValueError('input error!')
只要是合理的轉換邏輯就可以,但是,決不應該把一個IOError轉換成毫不相乾的ValueError。
小結
Python內置的try...except...finally用來處理錯誤十分方便。出錯時,會分析錯誤信息並定位錯誤發生的代碼位置才是最關鍵的。
程序也可以主動拋出錯誤,讓調用者來處理相應的錯誤。但是,應該在文檔中寫清楚可能會拋出哪些錯誤,以及錯誤產生的原因。
C. python運行錯誤怎麼辦
一、python的錯誤處理:
在程序運行的過程中,如果發生了錯誤,可以事先約定返回一個錯誤代碼,這樣,就可以知道是否有錯以及出錯的原因。
在操作系統提供的調用中,返回錯誤碼非常常見。比如打開文件的函數open(),成功時返迴文件的描述符(就是一個整數),出錯時返回-1用錯誤碼來表示是否出錯十分不便,因為函數本身應該返回的正常結果和錯誤碼混在一起,造成調用者必須大量的代碼來判斷是否出錯:def foo():
r = somefunction() if r == (-1): return (-1) return rdef bar():
r = foo() if r == (-1): print("Error") else: pass一旦出錯,還要一級一級上報,直到某個函數可以處理該錯誤(比如,給用戶輸出一個錯誤信息)
所以,高級語言通常都內置了一套try...except...finally...的錯誤處理機制,python也不例外。try
讓我們用一個例子來看看try的機制try: print("try....")
r = 10 / 0 print("result", r)except ZeroDivisionError as e: print("except:", e)finally: print("finally...")print("END....")
當我們認為某些代碼可能會出錯時,就可以用try來運行這段代碼,如果執行出錯,則後續代碼不會繼續執行
而是直接跳轉至錯誤處理代碼,即except語句塊
執行完except後,如果有finally語句塊,則執行finally語句塊,至此,執行完畢。
上面的代碼在計算10 / 0時 會產生一個除法運算錯誤:try....except: division by zerofinally...
END....>>>從輸出可以看到,當錯誤發生時,後續語句print("result:", r)不會被執行,except由於捕獲到ZeroDivisionError因此被執行。
最後,finally語句被執行。然後,程序繼續按照流程往下走。
如果把除數0 變成2,則執行結果如下try....
result 5.0finally...
END....>>>由於沒有錯誤發生,所以except語句塊不會被執行,但是finally如果有則一定會被執行,當然finally也可以沒有
你還可以猜測,錯誤應該有很多種類,日過發生了不同類型的錯誤,應該由不同的except語句塊處理。
沒錯,可以有多個except來捕獲不同類型的錯誤:try: print("try.....")
r = 10 / int("a") print("result:", r)except ValueError as e: print("ValueError:", e)except ZeroDivisionError as e: print("ZeroDivisionError:", e)finally: print("finally...")print("END...")
int()函數可能會拋出ValueError,所以我們用一個except捕獲ValueError,用另一個except捕獲ZeroDivisionError
此外,如果沒有錯誤發生,可以再except語句塊後面加一個else,當沒有錯誤發生時,會自動執行else語句。try: print("try...")
r = 10 / int("2") print("result:", r)except ValueError as e: print("ValueError:", e)except ZeroDivisionError as e: print("ZeroDivisionError:", e)else: print("No error!")finally: print("finally...")print("END")
python的錯誤其實也是class,所有的錯誤類型都繼承自BaseException,
所以在使用except時需要注意的是,它不但捕獲該類型的錯誤,還把其子類也「一網打盡」。
比如:try:
foo()except ValueError as e: print("ValueError")except UnicodeError as e: print("UnicodeError")
第二個except永遠也捕獲不到UnicodeError, 因為UnicodeError是ValueError的子類
如果有,也是被第一個except給捕獲了。
python所有的錯誤都是BaseException類派生的。
所有常見的錯誤類型和繼承關系看這里:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy使用try...exccept捕獲錯誤還有一個巨大的好處,就是可以跨越多層調用,比如函數main()調用foo()
foo()調用bar(),結果bar()出錯了,這時,只要main()捕獲到了,就可以處理:def foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main(): try:
bar("0") except Exception as e: print("Error:", e) finally: print("finally...")
也就是說,不需要在每個可能出錯的地方去捕獲異常,只要在合適的層次去捕獲就可以了。
這樣一來,就大大減少了寫 try...except...finally的麻煩。
二、調用堆棧
如果錯誤沒有被捕獲,他就會一直往上拋,最後被python解釋器捕獲,列印一個錯誤信息,然後程序退出。def foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main():
bar("0")
main()
執行結果為:
Traceback (most recent call last):
File "C:/Python36/test.py", line 10, in <mole>
main()
File "C:/Python36/test.py", line 8, in main
bar("0")
File "C:/Python36/test.py", line 5, in bar return foo(s) * 2
File "C:/Python36/test.py", line 2, in foo return 10 / int(s)
ZeroDivisionError: division by zero
出錯並不可怕,可怕的時不知道哪裡出錯了。解讀錯誤信息時定位錯誤的關鍵。
我們從上往下可以看到整個錯誤的調用函數鏈。
錯誤第一行:
Traceback (most recent call last):
這告訴我們的是錯誤的跟蹤信息。
File "C:/Python36/test.py", line 10, in < mole >main()
說明調用main()出錯了,在代碼文件test.py中第10行,但是原因是第8行:
File"C:/Python36/test.py", line8, in main
bar("0")
調用bar("0")出錯了,在代碼文件test.py中第8行,但原因是第5行:
File"C:/Python36/test.py", line5, in barreturn foo(s) * 2調用return foo(s) * 2時出錯了,在test.py中第5行,但原因是第2行
File "C:/Python36/test.py", line 2, in foo return 10 / int(s)
ZeroDivisionError: division by zero
這時我們找到了源頭,原來在第2行調用return 10 / int(s)出錯了,錯誤為ZeroDivisionError
三、記錄錯誤
如果不捕獲錯誤,自然可以讓python解釋器來列印出錯誤堆棧,但是程序也被結束了。
既然我們能捕獲錯誤,就可以把錯誤堆棧列印出來,然後分析錯誤原因,同時,讓程序繼續執行下去。
python內置的logging模塊可以非常容易地記錄錯誤信息:import loggingdef foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main(): try:
bar("0") except Exception as e:
logging.exception(e)
main()print("END")
輸出結果為:
ERROR:root:division by zero
Traceback (most recent call last):
File "C:/Python36/test.py", line 12, in main
bar("0")
File "C:/Python36/test.py", line 8, in bar return foo(s) * 2
File "C:/Python36/test.py", line 5, in foo return 10 / int(s)
ZeroDivisionError: division by zero
END
同樣是出錯,但程序列印完錯誤信息後會繼續執行,並正常退出。
通過配置,logging還可以把錯誤記錄到日誌文件里,方便事後排查。
四、拋出錯誤
因為錯誤是class,捕獲一個錯誤就是捕獲到該class的一個實例。
因此,錯誤並不是憑空產生的,而是有意創建並拋出的。
python的內置函數會拋出很多類型的錯誤,我們自己編寫的函數也可以拋出錯誤。
如果要拋出錯誤,首先根據需要,可以定義一個錯誤的class,選擇好繼承關系,然後用raise語句拋出一個錯誤的實例:class FooError(ValueError): passdef foo(s):
n = int(s) if n == 0: raise FooError("invalid value: %s" % s) return 10 / n
foo("0")
輸出結果:
Traceback (most recent call last):
File "C:/Python36/test.py", line 10, in <mole>
foo("0")
File "C:/Python36/test.py", line 7, in foo raise FooError("invalid value: %s" % s)
FooError: invalid value: 0
只有在必要的時候才定義我們自己的錯誤類型。
如果可以選擇python已有的內置錯誤類型(比如ValueError, TypeError),盡量使用python內置的錯誤類型。
最後,我們來看另一種錯誤處理方式:def foo(s):
n = int(s) if n == 0: raise ValueError("invalid value: %s" % s) return 10 / ndef bar(): try:
foo("0") except ValueError as e: print("ValieError") raisebar()
在bar()函數中,我們明明已經捕獲了錯誤,但是,列印一個ValueError之後
又通過raise語句拋出去了。這不是有病嗎
其實,這種錯誤處理方式不但沒病,而且相當常見。
捕獲錯誤目的只是記錄一下,便於或許追蹤。
但是,由於當前函數不知道應該怎麼處理該錯誤,所以,最恰當的方式是繼續往上拋,讓頂層調用者去處理。
好比一個員工處理不了一個問題時,就把問題一直往上拋,最終會拋給CEO去解決。
注意:raise語句如果不帶參數,就會把當前錯誤原樣拋出。
此外,在except中raise一個Error,還可以改寫錯誤類型try: 10 / 0except ZeroDivisionError: raise ValueError("do not input zero!")
輸出結果:
Traceback (most recent call last):
File "C:/Python36/test.py", line 4, in <mole> raise ValueError("do not input zero!")
ValueError: do not input zero!>>>只要是合理的轉換邏輯就可以,但是,絕不應該把一個IOError轉成毫不相乾的valueError.
總結:
python內置的 try...except...finally 用來處理錯誤十分方便。
出錯時,會分析錯誤信息並定位錯誤發生的代碼位置才是關鍵的。
程序也可以主動拋出錯誤,讓調用者來處理相應的錯誤。
但是應該在文檔中寫清楚可能會拋出哪些錯誤,以及錯誤產生的原因。
D. python查錯
請把錯誤信息貼上來
你的程序沒有縮進
如果你想對alist操作然後return alist,那麼你直接寫return alist就行了,而不是return swap(alist)
如果你想刪掉alist第八個元素,那麼應該寫del alist[7]
def swap(alist):
del alist[7]
for i in range(len(alist)):
if alist[i] ==2:
alist[i] = 3
return alist
l = [1,2,3,4,5,6,7,8]
l = swap(l)
print(l)
E. 找不出python的語法錯誤該如何解決
Python是一種解釋型語言,在開發中,沒有了編譯這個環節。大部分腳本語言都是解釋型語言。
沒有了編譯這個環節,在開發過程中,就無法知道自己所寫代碼的語法正確性,只有實際執行代碼才知道語法是否正確。這樣是不便於高效查錯的。
所以,才有開源項目pyflakes的出現,它專門用於python程序的早期查錯。
它使用起來非常簡單,首先用pip安裝(pip install --upgrade pyflakes),然後用這個命令(pyflakes xxx.py)就能檢查xxx.py文件中的錯誤。
下面是幾個例子:
例1:
python代碼(xxx.py文件中)
import os
for i in range(10)
print(i)
執行pyflakes xxx.py輸出的結果
main1.py:3:19: invalid syntax
for i in range(10)
^
分析:
根據提示,在代碼的第三行,語法錯誤
經檢查,是for中少寫了一個冒號
例2:
python代碼(xxx.py文件中)
import os
import time
import sys,os
for i in range(10):
print(i)
執行pyflakes xxx.py輸出的結果
main2.py:2: 'time' imported but unused
main2.py:3: redefinition of unused 'os' from line 1
main2.py:3: 'os' imported but unused
main2.py:3: 'sys' imported but unused
分析:
代碼第2行中,導入的time模塊並未使用
代碼第3行中的os多次導入(跟第1行重復)
例3:
python代碼
for i in range(10):
print(x)
執行pyflakes xxx.py輸出的結果
main3.py:2: undefined name 'x'
分析
代碼第2行,x並未定義
這屬於比較嚴重的錯誤,有時候可以發現變數名被敲錯
總結
本例中的錯誤,在實際代碼運行時,若走不到這個邏輯,運行也不會報錯。這留下了很嚴重的BUG,難以察覺。但用pyflakes,就能很快發現這些問題。
更多Python知識,請關註:Python自學網!!
F. python如何查看報錯日誌
test.py的39行,有個對象是個None?意思是你肯定有什麼對象沒有初始化就用了吧。
這個日誌提示的信息意思最後一行NoneType,你還是查查你的test.py調用的方法是不是不對
你可以在IDLE下單步執行看看,環境變數是不是有些沒有按照你想像的進行。
G. python里如何提取日誌中的錯誤信息
只要進行提取日誌中的錯誤信息,那麼你可以編輯一段程序,然後這樣的話才能夠完成達到提取的。
H. python 的報錯記錄
import requests
r =requests.get(" http://html.//www..com ")
def gethtmltext():
try:
r = requests.get(url, timeout =30)
r.raise_for_status()
r.encoding = 'utf-8'
return r.text
except:
return""
url = ' http://html.//www..com'
print (gethtmltext(url))
報錯:
TypeError: gethtmltext() takes 0 positional arguments but 1 was given
gethtmltext()函數沒有參數,但是在使用時給了一個參數
在gethtmltext中增添一個參數即可
即def gethtmltext(url):
I. python程序怎麼獲得控制台中的錯誤信息
嚴格來說,它們之間的不同就只有一個:視窗運行它們的時候調用不同的執行檔案。視窗用python.exe運行.py,用pythonw.exe運行.pyw。這純粹是因為安裝視窗版Python時,擴展名.py自動被登記為用python.exe運行的文件,而.pyw則被登記為用pythonw.exe運行。.py和.pyw之間的「其它差別」全都是python.exe和pythonw.exe之間的差別。跟python.exe比較起來,pythonw.exe有以下的不同:1)執行時不會彈出控制台窗口(也叫DOS窗口)2)所有向原有的stdout和stderr的輸出都無效3)所有從原有的stdin的讀取都只會得到EOF.pyw格式是被設計來運行開發完成的純圖形界面程序的。純圖形界面程序的用戶不需要看到控制台窗口。值得一提的是,開發純圖形界面程序的時候,你可以暫時把.pyw改成.py,以便運行時能調出控制台窗口,看到所有錯誤信息,方便除蟲。註:唯獨視窗版Python有.pyw格式。
J. python語法報錯日誌(更新中)
python高級語法
待拆分類別:
應該改為:
注意,傳入的參數a應該使用self.a定義。
改為:
錯誤同此link
x為FloatTensor,label為torch.int64。