真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

python函數(shù)錯誤獲取 python捕獲異常錯誤內(nèi)容

python出錯,請問是什么問題

要把代碼發(fā)現(xiàn)來才知道,以下是常見的錯誤

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站制作、秦安網(wǎng)絡(luò)推廣、微信小程序開發(fā)、秦安網(wǎng)絡(luò)營銷、秦安企業(yè)策劃、秦安品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供秦安建站搭建服務(wù),24小時服務(wù)熱線:18980820575,官方網(wǎng)址:www.cdcxhl.com

下面終于要講到當(dāng)你用到更多的Python的功能(數(shù)據(jù)類型,函數(shù),模塊,類等等)時可能碰到的問題了。由于篇幅有限,這里盡量精簡,尤其是對一些高級的概念。要想了解更多的細節(jié),敬請閱讀Learning Python, 2nd Edition的“小貼士”以及“Gotchas”章節(jié)。

打開文件的調(diào)用不使用模塊搜索路徑

當(dāng)你在Python中調(diào)用open()來訪問一個外部的文件時,Python不會使用模塊搜索路徑來定位這個目標(biāo)文件。它會使用你提供的絕對路徑,或者假定這個文件是在當(dāng)前工作目錄中。模塊搜索路徑僅僅為模塊加載服務(wù)的。

不同的類型對應(yīng)的方法也不同

列表的方法是不能用在字符串上的,反之亦然。通常情況下,方法的調(diào)用是和數(shù)據(jù)類型有關(guān)的,但是內(nèi)部函數(shù)通常在很多類型上都可以使用。舉個例子來說,列表的reverse方法僅僅對列表有用,但是len函數(shù)對任何具有長度的對象都適用

不能直接改變不可變數(shù)據(jù)類型

記住你沒法直接的改變一個不可變的對象(例如,元組,字符串):

T = (1, 2, 3)

T[2] = 4 # 錯誤

用切片,聯(lián)接等構(gòu)建一個新的對象,并根據(jù)需求將原來變量的值賦給它。因為Python會自動回收沒有用的內(nèi)存,因此這沒有看起來那么浪費:

T = T[:2] + (4,) # 沒問題了: T 變成了 (1, 2, 4)

使用簡單的for循環(huán)而不是while或者range

當(dāng)你要從左到右遍歷一個有序的對象的所有元素時,用簡單的for循環(huán)(例如,for x in seq:)相比于基于while-或者range-的計數(shù)循環(huán)而言會更容易寫,通常運行起來也更快。除非你一定需要,盡量避免在一個for循環(huán)里使用range:讓Python來替你解決標(biāo)號的問題。在下面的例子中三個循環(huán)結(jié)構(gòu)都沒有問題,但是第一個通常來說更好;在Python里,簡單至上。

S = "lumberjack"

for c in S: print c # 最簡單

for i in range(len(S)): print S[i] # 太多了

i = 0 # 太多了

while i len(S): print S[i]; i += 1

不要試圖從那些會改變對象的函數(shù)得到結(jié)果

諸如像方法list.append()和list.sort()一類的直接改變操作會改變一個對象,但不會將它們改變的對象返回出來(它們會返回None);正確的做法是直接調(diào)用它們而不要將結(jié)果賦值。經(jīng)常會看見初學(xué)者會寫諸如此類的代碼:

mylist = mylist.append(X)

目的是要得到append的結(jié)果,但是事實上這樣做會將None賦值給mylist,而不是改變后的列表。更加特別的一個例子是想通過用排序后的鍵值來遍歷一個字典里的各個元素,請看下面的例子:

D = {...}

for k in D.keys().sort(): print D[k]

差一點兒就成功了——keys方法會創(chuàng)建一個keys的列表,然后用sort方法來將這個列表排序——但是因為sort方法會返回None,這個循環(huán)會失敗,因為它實際上是要遍歷None(這可不是一個序列)。要改正這段代碼,將方法的調(diào)用分離出來,放在不同的語句中,如下:

Ks = D.keys()

Ks.sort()

for k in Ks: print D[k]

只有在數(shù)字類型中才存在類型轉(zhuǎn)換

在Python中,一個諸如123+3.145的表達式是可以工作的——它會自動將整數(shù)型轉(zhuǎn)換為浮點型,然后用浮點運算。但是下面的代碼就會出錯了:

S = "42"

I = 1

X = S + I # 類型錯誤

這同樣也是有意而為的,因為這是不明確的:究竟是將字符串轉(zhuǎn)換為數(shù)字(進行相加)呢,還是將數(shù)字轉(zhuǎn)換為字符串(進行聯(lián)接)呢?在Python中,我們認為“明確比含糊好”(即,EIBTI(Explicit is better than implicit)),因此你得手動轉(zhuǎn)換類型:

X = int(S) + I # 做加法: 43

X = S + str(I) # 字符串聯(lián)接: "421"

循環(huán)的數(shù)據(jù)結(jié)構(gòu)會導(dǎo)致循環(huán)

盡管這在實際情況中很少見,但是如果一個對象的集合包含了到它自己的引用,這被稱為循環(huán)對象(cyclic object)。如果在一個對象中發(fā)現(xiàn)一個循環(huán),Python會輸出一個[…],以避免在無限循環(huán)中卡?。?/p>

L = ['grail'] # 在 L中又引用L自身會

L.append(L) # 在對象中創(chuàng)造一個循環(huán)

L

['grail', [...]]

除了知道這三個點在對象中表示循環(huán)以外,這個例子也是很值得借鑒的。因為你可能無意間在你的代碼中出現(xiàn)這樣的循環(huán)的結(jié)構(gòu)而導(dǎo)致你的代碼出錯。如果有必要的話,維護一個列表或者字典來表示已經(jīng)訪問過的對象,然后通過檢查它來確認你是否碰到了循環(huán)。

賦值語句不會創(chuàng)建對象的副本,僅僅創(chuàng)建引用

這是Python的一個核心理念,有時候當(dāng)行為不對時會帶來錯誤。在下面的例子中,一個列表對象被賦給了名為L的變量,然后L又在列表M中被引用。內(nèi)部改變L的話,同時也會改變M所引用的對象,因為它們倆都指向同一個對象。

L = [1, 2, 3] # 共用的列表對象

M = ['X', L, 'Y'] # 嵌入一個到L的引用

M

['X', [1, 2, 3], 'Y']

L[1] = 0 # 也改變了M

M

['X', [1, 0, 3], 'Y']

通常情況下只有在稍大一點的程序里這就顯得很重要了,而且這些共用的引用通常確實是你需要的。如果不是的話,你可以明確的給他們創(chuàng)建一個副本來避免共用的引用;對于列表來說,你可以通過使用一個空列表的切片來創(chuàng)建一個頂層的副本:

L = [1, 2, 3]

M = ['X', L[:], 'Y'] # 嵌入一個L的副本

L[1] = 0 # 僅僅改變了L,但是不影響M

L

[1, 0, 3]

M

['X', [1, 2, 3], 'Y']

切片的范圍起始從默認的0到被切片的序列的最大長度。如果兩者都省略掉了,那么切片會抽取該序列中的所有元素,并創(chuàng)造一個頂層的副本(一個新的,不被公用的對象)。對于字典來說,使用字典的dict.copy()方法。

靜態(tài)識別本地域的變量名

Python默認將一個函數(shù)中賦值的變量名視作是本地域的,它們存在于該函數(shù)的作用域中并且僅僅在函數(shù)運行的時候才存在。從技術(shù)上講,Python是在編譯def代碼時,去靜態(tài)的識別本地變量,而不是在運行時碰到賦值的時候才識別到的。如果不理解這點的話,會引起人們的誤解。比如,看看下面的例子,當(dāng)你在一個引用之后給一個變量賦值會怎么樣:

X = 99

def func():

... print X # 這個時候還不存在

... X = 88 # 在整個def中將X視作本地變量

...

func( ) # 出錯了!

你會得到一個“未定義變量名”的錯誤,但是其原因是很微妙的。當(dāng)編譯這則代碼時,Python碰到給X賦值的語句時認為在這個函數(shù)中的任何地方X會被視作一個本地變量名。但是之后當(dāng)真正運行這個函數(shù)時,執(zhí)行print語句的時候,賦值語句還沒有發(fā)生,這樣Python便會報告一個“未定義變量名”的錯誤。

事實上,之前的這個例子想要做的事情是很模糊的:你是想要先輸出那個全局的X,然后創(chuàng)建一個本地的X呢,還是說這是個程序的錯誤?如果你真的是想要輸出這個全局的X,你需要將它在一個全局語句中聲明它,或者通過包絡(luò)模塊的名字來引用它。

默認參數(shù)和可變對象

在執(zhí)行def語句時,默認參數(shù)的值只被解析并保存一次,而不是每次在調(diào)用函數(shù)的時候。這通常是你想要的那樣,但是因為默認值需要在每次調(diào)用時都保持同樣對象,你在試圖改變可變的默認值(mutable defaults)的時候可要小心了。例如,下面的函數(shù)中使用一個空的列表作為默認值,然后在之后每一次函數(shù)調(diào)用的時候改變它的值:

def saver(x=[]): # 保存一個列表對象

... x.append(1) # 并每次調(diào)用的時候

... print x # 改變它的值

...

saver([2]) # 未使用默認值

[2, 1]

saver() # 使用默認值

[1]

saver() # 每次調(diào)用都會增加!

[1, 1]

saver()

[1, 1, 1]

有的人將這個視作Python的一個特點——因為可變的默認參數(shù)在每次函數(shù)調(diào)用時保持了它們的狀態(tài),它們能提供像C語言中靜態(tài)本地函數(shù)變量的類似的一些功能。但是,當(dāng)你第一次碰到它時會覺得這很奇怪,并且在Python中有更加簡單的辦法來在不同的調(diào)用之間保存狀態(tài)(比如說類)。

要擺脫這樣的行為,在函數(shù)開始的地方用切片或者方法來創(chuàng)建默認參數(shù)的副本,或者將默認值的表達式移到函數(shù)里面;只要每次函數(shù)調(diào)用時這些值在函數(shù)里,就會每次都得到一個新的對象:

def saver(x=None):

... if x is None: x = [] # 沒有傳入?yún)?shù)?

... x.append(1) # 改變新的列表

... print x

...

saver([2]) # 沒有使用默認值

[2, 1]

saver() # 這次不會變了

[1]

saver()

[1]

其他常見的編程陷阱

下面列舉了其他的一些在這里沒法詳述的陷阱:

在頂層文件中語句的順序是有講究的:因為運行或者加載一個文件會從上到下運行它的語句,所以請確保將你未嵌套的函數(shù)調(diào)用或者類的調(diào)用放在函數(shù)或者類的定義之后。

reload不影響用from加載的名字:reload最好和import語句一起使用。如果你使用from語句,記得在reload之后重新運行一遍from,否則你仍然使用之前老的名字。

在多重繼承中混合的順序是有講究的:這是因為對superclass的搜索是從左到右的,在類定義的頭部,在多重superclass中如果出現(xiàn)重復(fù)的名字,則以最左邊的類名為準(zhǔn)。

在try語句中空的except子句可能會比你預(yù)想的捕捉到更多的錯誤。在try語句中空的except子句表示捕捉所有的錯誤,即便是真正的程序錯誤,和sys.exit()調(diào)用,也會被捕捉到。

如何解決python報錯找不到主函數(shù)的錯誤

解決python報錯找不到主函數(shù)錯誤的方法:

在代碼的最下方加上“if __name__ == '__main__':”主函數(shù)語句,將需要使用的代碼語句放到該語句下面就可以了

示例如下:

更多Python知識,請關(guān)注:Python自學(xué)網(wǎng)??!

python運行錯誤怎么辦?

一、python的錯誤處理:

在程序運行的過程中,如果發(fā)生了錯誤,可以事先約定返回一個錯誤代碼,這樣,就可以知道是否有錯以及出錯的原因。

在操作系統(tǒng)提供的調(diào)用中,返回錯誤碼非常常見。比如打開文件的函數(shù)open(),成功時返回文件的描述符(就是一個整數(shù)),出錯時返回-1用錯誤碼來表示是否出錯十分不便,因為函數(shù)本身應(yīng)該返回的正常結(jié)果和錯誤碼混在一起,造成調(diào)用者必須大量的代碼來判斷是否出錯:def foo():

r = somefunction() ? ?if r == (-1): ? ? ? ?return (-1) ? ?return rdef bar():

r = foo() ? ?if r == (-1): ? ? ? ?print("Error") ? ?else: ? ? ? ?pass一旦出錯,還要一級一級上報,直到某個函數(shù)可以處理該錯誤(比如,給用戶輸出一個錯誤信息)

所以,高級語言通常都內(nèi)置了一套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....")

當(dāng)我們認為某些代碼可能會出錯時,就可以用try來運行這段代碼,如果執(zhí)行出錯,則后續(xù)代碼不會繼續(xù)執(zhí)行

而是直接跳轉(zhuǎn)至錯誤處理代碼,即except語句塊

執(zhí)行完except后,如果有finally語句塊,則執(zhí)行finally語句塊,至此,執(zhí)行完畢。

上面的代碼在計算10 / 0時 會產(chǎn)生一個除法運算錯誤:try....except: division by zerofinally...

END....從輸出可以看到,當(dāng)錯誤發(fā)生時,后續(xù)語句print("result:", r)不會被執(zhí)行,except由于捕獲到ZeroDivisionError因此被執(zhí)行。

最后,finally語句被執(zhí)行。然后,程序繼續(xù)按照流程往下走。

如果把除數(shù)0 變成2,則執(zhí)行結(jié)果如下try....

result 5.0finally...

END....由于沒有錯誤發(fā)生,所以except語句塊不會被執(zhí)行,但是finally如果有則一定會被執(zhí)行,當(dāng)然finally也可以沒有

你還可以猜測,錯誤應(yīng)該有很多種類,日過發(fā)生了不同類型的錯誤,應(yīng)該由不同的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()函數(shù)可能會拋出ValueError,所以我們用一個except捕獲ValueError,用另一個except捕獲ZeroDivisionError

此外,如果沒有錯誤發(fā)生,可以再except語句塊后面加一個else,當(dāng)沒有錯誤發(fā)生時,會自動執(zhí)行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時需要注意的是,它不但捕獲該類型的錯誤,還把其子類也“一網(wǎng)打盡”。

比如:try:

foo()except ValueError as e: ? ?print("ValueError")except UnicodeError as e: ? ?print("UnicodeError")

第二個except永遠也捕獲不到UnicodeError, 因為UnicodeError是ValueError的子類

如果有,也是被第一個except給捕獲了。

python所有的錯誤都是BaseException類派生的。

所有常見的錯誤類型和繼承關(guān)系看這里:

使用try...exccept捕獲錯誤還有一個巨大的好處,就是可以跨越多層調(diào)用,比如函數(shù)main()調(diào)用foo()

foo()調(diào)用bar(),結(jié)果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的麻煩。

二、調(diào)用堆棧

如果錯誤沒有被捕獲,他就會一直往上拋,最后被python解釋器捕獲,打印一個錯誤信息,然后程序退出。def foo(s): ? ?return 10 / int(s)def bar(s): ? ?return foo(s) * 2def main():

bar("0")

main()

執(zhí)行結(jié)果為:

Traceback (most recent call last):

File "C:/Python36/test.py", line 10, in module

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

出錯并不可怕,可怕的時不知道哪里出錯了。解讀錯誤信息時定位錯誤的關(guān)鍵。

我們從上往下可以看到整個錯誤的調(diào)用函數(shù)鏈。

錯誤第一行:

Traceback (most recent call last):

這告訴我們的是錯誤的跟蹤信息。

File "C:/Python36/test.py", line 10, in module main()

說明調(diào)用main()出錯了,在代碼文件test.py中第10行,但是原因是第8行:

File"C:/Python36/test.py", line8, in main

bar("0")

調(diào)用bar("0")出錯了,在代碼文件test.py中第8行,但原因是第5行:

File"C:/Python36/test.py", line5, in barreturn foo(s) * 2調(diào)用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行調(diào)用return 10 / int(s)出錯了,錯誤為ZeroDivisionError

三、記錄錯誤

如果不捕獲錯誤,自然可以讓python解釋器來打印出錯誤堆棧,但是程序也被結(jié)束了。

既然我們能捕獲錯誤,就可以把錯誤堆棧打印出來,然后分析錯誤原因,同時,讓程序繼續(xù)執(zhí)行下去。

python內(nèi)置的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")

輸出結(jié)果為:

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

同樣是出錯,但程序打印完錯誤信息后會繼續(xù)執(zhí)行,并正常退出。

通過配置,logging還可以把錯誤記錄到日志文件里,方便事后排查。

四、拋出錯誤

因為錯誤是class,捕獲一個錯誤就是捕獲到該class的一個實例。

因此,錯誤并不是憑空產(chǎn)生的,而是有意創(chuàng)建并拋出的。

python的內(nèi)置函數(shù)會拋出很多類型的錯誤,我們自己編寫的函數(shù)也可以拋出錯誤。

如果要拋出錯誤,首先根據(jù)需要,可以定義一個錯誤的class,選擇好繼承關(guān)系,然后用raise語句拋出一個錯誤的實例:class FooError(ValueError): ? ?passdef foo(s):

n = ?int(s) ? ?if n == 0: ? ? ? ?raise FooError("invalid value: %s" % s) ? ?return 10 / n

foo("0")

輸出結(jié)果:

Traceback (most recent call last):

File "C:/Python36/test.py", line 10, in module

foo("0")

File "C:/Python36/test.py", line 7, in foo ? ?raise FooError("invalid value: %s" % s)

FooError: invalid value: 0

只有在必要的時候才定義我們自己的錯誤類型。

如果可以選擇python已有的內(nèi)置錯誤類型(比如ValueError, TypeError),盡量使用python內(nèi)置的錯誤類型。

最后,我們來看另一種錯誤處理方式: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()函數(shù)中,我們明明已經(jīng)捕獲了錯誤,但是,打印一個ValueError之后

又通過raise語句拋出去了。這不是有病嗎

其實,這種錯誤處理方式不但沒病,而且相當(dāng)常見。

捕獲錯誤目的只是記錄一下,便于或許追蹤。

但是,由于當(dāng)前函數(shù)不知道應(yīng)該怎么處理該錯誤,所以,最恰當(dāng)?shù)姆绞绞抢^續(xù)往上拋,讓頂層調(diào)用者去處理。

好比一個員工處理不了一個問題時,就把問題一直往上拋,最終會拋給CEO去解決。

注意:raise語句如果不帶參數(shù),就會把當(dāng)前錯誤原樣拋出。

此外,在except中raise一個Error,還可以改寫錯誤類型try: ? ?10 / 0except ZeroDivisionError: ? ?raise ValueError("do not input zero!")

輸出結(jié)果:

Traceback (most recent call last):

File "C:/Python36/test.py", line 4, in module ? ?raise ValueError("do not input zero!")

ValueError: do not input zero!只要是合理的轉(zhuǎn)換邏輯就可以,但是,絕不應(yīng)該把一個IOError轉(zhuǎn)成毫不相干的valueError.

總結(jié):

python內(nèi)置的 try...except...finally 用來處理錯誤十分方便。

出錯時,會分析錯誤信息并定位錯誤發(fā)生的代碼位置才是關(guān)鍵的。

程序也可以主動拋出錯誤,讓調(diào)用者來處理相應(yīng)的錯誤。

但是應(yīng)該在文檔中寫清楚可能會拋出哪些錯誤,以及錯誤產(chǎn)生的原因。

python 的常用內(nèi)置函數(shù) && 錯誤

斷言

logging:把print()替換為logging是第3種調(diào)試程序錯誤信息方式

pdb :調(diào)試器pdb,讓程序以單步方式運行,可以隨時查看運行狀態(tài)

pdb.set_trace() :調(diào)試常用

IDE

如果要比較爽地設(shè)置斷點、單步執(zhí)行,就需要一個支持調(diào)試功能的IDE.


網(wǎng)頁題目:python函數(shù)錯誤獲取 python捕獲異常錯誤內(nèi)容
網(wǎng)頁URL:http://weahome.cn/article/hjcpdh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部