In letzter Zeit bin ich bei kleinen Projekten häufig auf Python-Ausnahmen gestoßen, was den Leuten große Kopfschmerzen bereitet. Deshalb habe ich die Ausnahmen organisiert, um zu vermeiden, dass sie beim nächsten Mal mit Ausnahmen überfordert werden.
1.Python-Ausnahmeklasse
异常 | 描述 |
NameError | 尝试访问一个没有申明的变量 |
ZeroDivisionError | 除数为0 |
SyntaxError | 语法错误 |
IndexError | 索引超出序列范围 |
KeyError | 请求一个不存在的字典关键字 |
IOError | 输入输出错误(比如你要读的文件不存在) |
AttributeError | 尝试访问未知的对象属性 |
ValueError | 传给函数的参数类型不正确,比如给int()函数传入字符 |
2. Ausnahmen abfangen
Pythons vollständige Anweisung zum Abfangen von Ausnahmen sieht in etwa so aus:
try: try_suite except Exception1,Exception2,...,Argument: exception_suite ...... #other exception block else: no_exceptions_detected_suite finally: always_execute_suite
Ähm... ist das nicht kompliziert? Wenn wir eine Ausnahme abfangen wollen, müssen wir sie natürlich nicht vollständig im oben genannten Format ausschreiben. Wir können die else-Anweisung oder die final-Anweisung wegwerfen, aber wir brauchen sie nicht Behalten Sie die endgültige Aussage bei. Ähm, ohnmächtig geworden? Okay, lasst uns sie einzeln erklären.
2.1 try...exclusive... Statement
Selbstverständlich ist try_suite der Code, den wir zum Abfangen von Ausnahmen benötigen. Die „exclusive“-Anweisung ist der Schlüssel. Nachdem unser Versuch die Ausnahme im Codesegment „try_suite“ erfasst hat, wird sie von „exclusive“ behandelt.
Die einfachste Form der try...exclusive-Anweisung lautet wie folgt:
try: try_suite except: exception block
Auf die obige Ausnahmeklausel folgen keine Ausnahmen und Ausnahmeparameter. Unabhängig davon, ob der Versuch eine Ausnahme abfängt, wird diese zur Verarbeitung an den Ausnahmeblock der Ausnahmeklausel übergeben. Was ist, wenn wir beispielsweise eine bestimmte Ausnahme behandeln möchten, wir möchten nur die Division-durch-Null-Ausnahme behandeln und andere Ausnahmen auslösen, ohne sie zu behandeln. Zu diesem Zeitpunkt müssen wir den Ausnahmeparameter an die Ausnahmeklausel übergeben! Dass ExceptionN die Ausnahmeklasse ist, die wir der Ausnahmeklausel zuweisen möchten (siehe Tabelle der Ausnahmeklassen), was bedeutet, dass, wenn diese Art von Ausnahme abgefangen wird, sie von dieser Ausnahmeklausel behandelt wird. Zum Beispiel:
try: try_suite except Exception: exception block
Zum Beispiel:
>>> try: ... res = 2/0 ... except ZeroDivisionError: ... print "Error:Divisor must not be zero!" ... Error:Divisor must not be zero!
Sehen Sie, wir haben wirklich die Ausnahme „ZeroDivisionError“ entdeckt! Was ist, wenn ich mehrere Ausnahmen abfangen und behandeln möchte? Es gibt zwei Möglichkeiten: Die eine besteht darin, mehrere Ausnahmeklassenparameter an eine Ausnahmeklausel zu übergeben, die andere darin, mehrere Ausnahmeklauseln zu schreiben, und jede Klausel übergibt die Ausnahmeklassenparameter, die Sie behandeln möchten. Diese beiden Verwendungszwecke können sogar gemischt und kombiniert werden! Lassen Sie mich Ihnen ein Beispiel geben.
try: floatnum = float(raw_input("Please input a float:")) intnum = int(floatnum) print 100/intnum except ZeroDivisionError: print "Error:you must input a float num which is large or equal then 1!" except ValueError: print "Error:you must input a float num!" [root@Cherish tmp]# python test.py Please input a float:fjia Error:you must input a float num! [root@Cherish tmp]# python test.py Please input a float:0.9999 Error:you must input a float num which is large or equal then 1! [root@Cherish tmp]# python test.py Please input a float:25.091 4
Das obige Beispiel kann jeder auf einen Blick verstehen, daher werde ich es nicht weiter erklären. Solange jeder versteht, dass unsere Ausnahme eine Ausnahme, mehrere Ausnahmen oder sogar alle Ausnahmen behandeln kann.
Ihnen ist vielleicht aufgefallen, dass wir nicht erklärt haben, was das Argument nach der Ausnahmeklausel ist? Mach dir keine Sorgen, hör mir einfach zu. Dieses Argument ist tatsächlich eine Instanz der Ausnahmeklasse (sagen Sie mir nicht, dass Sie nicht wissen, was eine Instanz ist) und enthält Diagnoseinformationen aus dem Ausnahmecode. Das heißt, wenn Sie eine Ausnahme abfangen, können Sie über eine Instanz der Ausnahmeklasse weitere Informationen über die Ausnahme abrufen. Zum Beispiel:
>>> try: ... 1/0 ... except ZeroDivisionError,reason: ... pass ... >>> type(reason) <type 'exceptions.ZeroDivisionError'> >>> print reason integer division or modulo by zero >>> reason ZeroDivisionError('integer division or modulo by zero',) >>> reason.__class__ <type 'exceptions.ZeroDivisionError'> >>> reason.__class__.__doc__ 'Second argument to a division or modulo operation was zero.' >>> reason.__class__.__name__ 'ZeroDivisionError'
Im obigen Beispiel haben wir die Division-durch-Null-Ausnahme abgefangen, aber nichts unternommen. Dieser Grund ist eine Instanz der Ausnahmeklasse ZeroDivisionError, die über den Typ erkennbar ist.
2.2 Versuchen Sie ... außer... else-Anweisung
Lassen Sie uns nun über diese else-Anweisung sprechen. Es gibt viele spezielle Verwendungsmöglichkeiten von else in Python, beispielsweise für Bedingungen und Schleifen. Wenn man es in eine try-Anweisung einfügt, hat es fast den gleichen Effekt: Wenn keine Ausnahme erkannt wird, wird die else-Anweisung ausgeführt. Lassen Sie uns ein Beispiel geben, damit Sie es besser verstehen:
>>> import syslog >>> try: ... f = open("/root/test.py") ... except IOError,e: ... syslog.syslog(syslog.LOG_ERR,"%s"%e) ... else: ... syslog.syslog(syslog.LOG_INFO,"no exception caught\n") ... >>> f.close()
2.3 Schlusserklärung
finally-Klausel ist ein Codeteil, der unabhängig davon ausgeführt wird, ob eine Ausnahme erkannt wird oder nicht. Wir können die Ausnahme-Klausel und die Else-Klausel wegwerfen und try...finally allein oder in Kombination mit Ausnahme usw. verwenden.
Wenn beispielsweise in 2.2 andere Ausnahmen auftreten, die nicht abgefangen werden können und das Programm abnormal beendet wird, wird Datei f nicht normal geschlossen. Dies ist nicht das Ergebnis, das wir sehen möchten, aber wenn wir die f.close-Anweisung in die final-Anweisung einfügen, wird die Datei normal geschlossen, unabhängig davon, ob eine Ausnahme vorliegt. Wäre das nicht wunderbar?
Code kopieren
>>> import syslog >>> try: ... f = open("/root/test.py") ... except IOError,e: ... syslog.syslog(syslog.LOG_ERR,"%s"%e) ... else: ... syslog.syslog(syslog.LOG_INFO,"no exception caught\n") ... finally: >>> f.close()
3. Zwei spezielle und praktische Methoden zur Behandlung von Ausnahmen
assert expression[,reason]
>>> assert len('love') == len('like') >>> assert 1==1 >>> assert 1==2,"1 is not equal 2!" Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError: 1 is not equal 2!
>>> try: ... assert 1 == 2 , "1 is not equal 2!" ... except AssertionError,reason: ... print "%s:%s"%(reason.__class__.__name__,reason) ... AssertionError:1 is not equal 2! >>> type(reason) <type 'exceptions.AssertionError'>
mit context_expr [as var]:
with_suite
>>> with open('/root/test.py') as f: ... for line in f: ... print line
上面这几行代码干了什么?
(1)打开文件/root/test.py
(2)将文件对象赋值给 f
(3)将文件所有行输出
(4)无论代码中是否出现异常,Python都会为我们关闭这个文件,我们不需要关心这些细节。
这下,是不是明白了,使用with语句来使用这些共享资源,我们不用担心会因为某种原因而没有释放他。但并不是所有的对象都可以使用with语句,只有支持上下文管理协议(context management protocol)的对象才可以,那哪些对象支持该协议呢?如下表
file
decimal.Contex
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore
至于什么是上下文管理协议,如果你不只关心怎么用with,以及哪些对象可以使用with,那么我们就不比太关心这个问题
4.抛出异常(raise)
如果我们想要在自己编写的程序中主动抛出异常,该怎么办呢?raise语句可以帮助我们达到目的。其基本语法如下:
raise [SomeException [, args [,traceback]]
第一个参数,SomeException必须是一个异常类,或异常类的实例
第二个参数是传递给SomeException的参数,必须是一个元组。这个参数用来传递关于这个异常的有用信息。
第三个参数traceback很少用,主要是用来提供一个跟中记录对(traceback)
下面我们就来列举几个 例子:
>>> raise NameError Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError >>> raise NameError() #异常类的实例 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError >>> raise NameError,("There is a name error","in test.py") Traceback (most recent call last): File "<stdin>", line 1, in <module> >>> raise NameError("There is a name error","in test.py") #注意跟上面一个例子的区别 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: ('There is a name error', 'in test.py') >>> raise NameError,NameError("There is a name error","in test.py") #注意跟上面一个例子的区别 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: ('There is a name error', 'in test.py')
其实,我们最常用的还是,只传入第一个参数用来指出异常类型,最多再传入一个元组,用来给出说明信息。如上面第三个例子。
5.异常和sys模块
另一种获取异常信息的途径是通过sys模块中的exc_info()函数。该函数回返回一个三元组:(异常类,异常类的实例,跟中记录对象)
>>> try: ... 1/0 ... except: ... import sys ... tuple = sys.exc_info() ... >>> print tuple (<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x7f538a318b48>) >>> for i in tuple: ... print i ... <type 'exceptions.ZeroDivisionError'> #异常类 integer division or modulo by zero #异常类的实例 <traceback object at 0x7f538a318b48> #跟踪记录对象
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!