>  기사  >  백엔드 개발  >  Python 예외 처리 요약

Python 예외 처리 요약

WBOY
WBOY원래의
2016-12-05 13:27:151019검색

최근 소규모 프로젝트를 하다 보면 Python 예외가 자주 발생하는데, 이로 인해 사람들이 매우 골치 아프게 됩니다. 그래서 다음에 예외를 만났을 때 당황하지 않도록 예외를 정리했습니다.

1.Python 예외 클래스

异常 描述
NameError 尝试访问一个没有申明的变量
ZeroDivisionError 除数为0
SyntaxError 语法错误
IndexError 索引超出序列范围
KeyError 请求一个不存在的字典关键字
IOError 输入输出错误(比如你要读的文件不存在)
AttributeError 尝试访问未知的对象属性
ValueError 传给函数的参数类型不正确,比如给int()函数传入字符

2. 예외 잡기

Python의 완전한 예외 포착 명령문은 다음과 같습니다.

try:
 try_suite
except Exception1,Exception2,...,Argument:
 exception_suite
...... #other exception block
else:
 no_exceptions_detected_suite
finally:
 always_execute_suite

음... 복잡하지 않나요? 물론, 예외를 포착하고 싶을 때 위의 형식으로 완전히 작성할 필요는 없습니다. else 문이나 finally 문도 필요하지 않습니다. 마지막 진술을 유지하십시오. 음, 기절했나요? 좋아요, 하나씩 설명해 보겠습니다.

2.1 try...out...문

말할 필요도 없이 try_suite는 예외를 포착하는 데 필요한 코드입니다. Except 문이 핵심입니다. try가 코드 세그먼트 try_suite에서 예외를 캡처한 후에는 Except가 처리됩니다.

try...Exception 문의 가장 간단한 형태는 다음과 같습니다.

try:
 try_suite
except:
 exception block
  

위의 Except 절 뒤에는 예외 및 예외 매개변수가 없으므로 Try가 예외를 포착하는지 여부에 관계없이 처리를 위해 Except 절의 예외 블록으로 넘겨집니다. 예를 들어, 특정 예외를 처리하려면 어떻게 해야 할까요? 예를 들어 0으로 나누기 예외만 처리하고 다른 예외가 발생하면 이를 처리하지 않고 발생하도록 놔두어야 합니다. 이때, Except 절에 예외 매개변수를 전달해야 합니다! ExceptionN은 제외 절에 제공하려는 예외 클래스입니다(예외 클래스 표 참조). 이는 이러한 유형의 예외가 발견되면 이 제외 절에 의해 처리된다는 의미입니다. 예:

try:
 try_suite
except Exception:
 exception block
 

예:

>>> try:
...  res = 2/0
... except ZeroDivisionError:
...  print "Error:Divisor must not be zero!"
... 
Error:Divisor must not be zero!

보세요, 실제로 ZeroDivisionError 예외를 포착했습니다! 그렇다면 여러 예외를 포착하고 처리하려면 어떻게 해야 할까요? 두 가지 방법이 있습니다. 하나는 여러 개의 예외 클래스 매개변수를 제외 절에 전달하는 것이고, 다른 하나는 여러 개의 제외 절을 작성하는 것입니다. 각 절은 처리하려는 예외 클래스 매개변수를 전달합니다. 심지어 이 두 가지 사용법을 혼합하여 사용할 수도 있습니다! 예를 들어 보겠습니다.

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

위의 예는 누구나 한 눈에 이해할 수 있으므로 더 이상 설명하지 않겠습니다. 우리의 예외가 하나의 예외, 여러 예외 또는 심지어 모든 예외를 처리할 수 있다는 것을 모든 사람이 이해하는 한 말입니다.

Except 절 뒤에 인수가 무엇인지 설명하지 않았다는 것을 눈치채셨나요? 걱정하지 말고 내 말을 들어보세요. 이 인수는 실제로 예외 클래스의 인스턴스(인스턴스가 무엇인지 모른다고 말하지 마세요)이며 예외 코드의 진단 정보를 포함합니다. 즉, 예외를 포착하면 예외 클래스의 인스턴스를 통해 예외에 대한 자세한 정보를 얻을 수 있습니다. 예:

>>> 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'

위의 예에서는 0으로 나누기 예외를 포착했지만 아무 작업도 수행하지 않았습니다. 그 이유는 유형을 통해 볼 수 있는 예외 클래스 ZeroDivisionError의 인스턴스 때문입니다.

2.2 try ... Except... else 문

이제 else 문에 대해 이야기해 보겠습니다. 조건문이나 루프와 같이 Python에는 else의 특별한 용도가 많이 있습니다. try 문에 넣으면 효과는 거의 같습니다. 예외가 감지되지 않으면 else 문이 실행됩니다. 이해를 돕기 위해 예를 들어보겠습니다.

>>> 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 finally 선언

finally 절은 예외 감지 여부에 관계없이 실행되는 코드 조각입니다. Except 절과 else 절을 ​​버리고 try...finally를 단독으로 사용하거나 Except 등과 함께 사용할 수 있습니다.

예를 들어 2.2에서 잡을 수 없는 다른 예외가 발생하여 프로그램이 비정상적으로 종료되면 파일 f가 정상적으로 닫히지 않습니다. 이는 우리가 보고 싶은 결과는 아니지만, finally 문에 f.close 문을 넣으면 예외 여부와 관계없이 파일이 정상적으로 닫히게 되니 정말 멋지지 않을까요

코드 복사

>>> 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. 예외 처리를 위한 특별하고 편리한 두 가지 방법

3.1 주장

어설션이란 무엇입니까? 먼저 구문을 살펴보겠습니다.

표현 주장[,이유]

assert는 주장의 키워드입니다. 이 문을 실행할 때 표현식이 먼저 평가되고, 표현식이 true가 아니면 아무 작업도 수행되지 않습니다. 이유는 이전에 이야기한 예외 클래스 인스턴스와 동일합니다. 몰라? 상관없어요. 예를 들어주세요! 가장 실용적입니다!

>>> 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!

assertion 이후의 표현식이 true이면 아무 작업도 수행되지 않는다는 것을 알 수 있습니다. true가 아니면 AssertionErro 예외가 발생하고 우리가 전달한 문자열이 예외 클래스의 특정 인스턴스로 사용됩니다. .정보가 존재합니다. 실제로, try 블록에서도 Assert 예외를 포착할 수 있습니다.

>>> 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'>

3.2. 컨텍스트 관리(문 포함)

공유 리소스(예: 파일, 데이터)의 고유한 할당을 보장하기 위해 try, Except, finally 코드를 사용하고 작업이 끝난 후 해제한다면 운이 좋을 것입니다! 이 with 문은 try, Except, 그리고 마지막으로 여러분을 자유롭게 할 수 있습니다! 구문은 다음과 같습니다.

context_expr [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> #跟踪记录对象

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.