• 说说Python中的异常及异常处理方式
  • 发布于 2个月前
  • 99 热度
    0 评论
  • 林锦健
  • 4 粉丝 6 篇博客
  •   

写在之前

从今天开始一个新的篇章又要开始了,这次要写的「错误 & 异常」知识点比较少,不像「类」那样知识点那么多,所以稍微好过一点。

对于程序在执行过程中因为错误或者其它原因而中止的现象,我们在之前文章的代码中已经看过很多次了,那些都可以归为「错误 & 异常」现象,我们接下来就是要对这种现象进行近距离的观察和处理。


错误

其实不管是弱鸡还是大佬,在写代码的时候错误往往是难以避免的,可能是因为手残,也可能是因为拼写错误,当然还有可能是某些比较玄学的错误,比如逗号写成全角的等等等等。总之,写代码中有相当一部分工作就是要不停的修改错误。

Python 中的错误之一就是「语法错误」(Syntax Errors),比如:

>>> for i in range(5)
 File "<stdin>", line 1
   for i in range(5)
                   ^
SyntaxError: invalid syntax


上面的那行代码里因为缺少冒号,导致解释器无法解释,于是报错,这个报错其实是 Python 的语法分析器完成的,并检测到了错误所在的文件和行号( File "<stdin>", line 1 ),还以向上的箭头 ^ 标识错误的位置,最后显示错误类型。

另一种错误就是我们常说的「逻辑错误」,逻辑错误可能是由不合法或者不完整的输入导致的,也可能是无法计算等,或者是其它的逻辑问题。逻辑错误不是由 Python 来检查的,所以此处我们所谈的错误不包括逻辑错误。


异常

当 Python 检测到一个错误时,解释器就无法继续执行下去,于是就抛出提示信息,即为「异常」。有错误时,程序运行过程就会出现异常,让我们先来看一个小例子:

>>> 10 / 0
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero


当 Python 抛出异常的时候,首先有「跟踪记录」或者叫「回溯」,后面显示异常的详细信息,包括异常所在的位置,最后一行是异常类型及导致异常的原因。在上面的例子中,明确的告诉我们异常的类型是 ZeroDivisionError,并且对此异常类型做了解释。


异常的类型有很多,我在这说几个常见的类型:

NameError
尝试访问一个没有申明的变量

ZeroDivisionError
除数为零

SyntaxError
语法错误

IndexError
索引超出序列范围

KeyError
请求一个不存在的字典关键字

IOError
输入/输出错误

AttributeError
尝试访问未知的对象属性

为了能够更好的深入理解,我在这举几个例子,展示一下其中几个异常出现的条件和结果:

1.NameError

>>> rocky
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name 'rocky' is not defined


在 Python 中虽然不需要在使用变量之前声明类型,但也需要对变量进行赋值,然后才可以使用,不被赋值的变量不能在 Python 中存在,因为变量相当于一个便签,要把它贴到对象上才有意义。

2.IndexError & KeyError

>>> a = [1,2,3]
>>> a[4]
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
IndexError: list index out of range

>>> b = {'name':'rocky'}
>>> b['age']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'age'


这两个用我们俗语来说就是「鸡蛋里挑骨头」,一定得报错了,不过在实际编程的时候,特别是循环的时候,常常由于循环条件设置的不合理从而出现这种类型的错误。

3.IOError

>>> f = open('test')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'test'


如果你确认有文件,就一定要把路径写正确,因为你并没有告诉 Python 要对你的计算机进行全身搜查,所以 Python 会按照你指定的未知去找,找不到就会出现异常。


这里只是干说其实没有什么效果,具体的还是要在实际编程中碰到才会印象深刻,这里你先把常见的几个记住,到时候别出现问题的时候不知道是什么错误。


处理异常

首先,让我们先来看一段代码:

while True:
   print('this is a division program.')
   a = input("input 'a' continue,otherwise logout:")
   if a == 'a':
       x = input('first number')
       y = input('second number')
       try:
           print(float(x)/float(y))
           print('***************')
       except ZeroDivisionError:
           print('the second number can not be zero.')
           print('***********************************')

   else:
       break

运行上面的代码,显示的结果如下:

this is a division program.
input 'a' continue,otherwise logout:a
first number5
second number2
2.5
***************
this is a division program.
input 'a' continue,otherwise logout:a
first number5
second number0
the second number can not be zero.
***********************************
this is a division program.
input 'a' continue,otherwise logout:b

从运行的情况来看,当在第 2 个数,即除数为 0 时,程序并没有因为这个错误而停止,而是给了一个很友好的提示,让我们有机会改正错误,这完全得益于「异常处理」的设置,如果没有处理异常的机制,当异常出现的时候程序就会中止。

1.try...except...

对于上面的例子,只看到了 try 和 except 部分,如果没有异常发生的话,except 在 try 执行后被忽略;如果 try 子句中有异常的话,则该部分的其它子句被忽略,直接跳到 except 部分,执行其后面指定的异常类型及其子句。

except 后面也可以没有任何异常类型,即无异常参数。如何这样的话,不论 try 部分发生什么异常,都会执行 except。

2.处理多个异常

try...except... 是处理异常的基本方式,在此基础上,还可以扩展,也就是能够处理多个异常。

这里所说的处理多个异常,并不是因为同时报出多个异常,而是程序在运行中,只要遇到一个异常就会反应,所以每次捕捉到的异常一定是一个,由不同的 except 子句处理。

3. else 子句

其实有了 try...except...,在一般情况下是够用的,但怕就怕在总有不一般的情况出现,所以就增加一个 else 子句,这个其实就和我们说的话一样,总要根据需要添加不少东西。

try:
   print('just try')
except:
   print('just except')
else:
   print('i am else')

上述代码的运行结果如下:

just try
i am else

上述代码能够帮助我们理解 else 的执行特点:如果 try 被执行了,则 except 被忽略,但是 else 被执行。然后我们在来看下面的代码:

try:
   print(1/0)
except:
   print('just except')
else:
   print('i am else')

上述代码的运行结果如下:

just except

这个时候,else 就不被执行了,两个例子帮助我们了解了 else 的执行特点。

4.finally

finally 子句,一看这个名字,就感觉这是做善后工作的。的确如此,如果有了 finally ,不管前面执行的是 try 还是 except,最终都要执行它。因此,有一种说法是将 finally 用在可能的异常后进行清理,请看下面的例子:

x = 10

try:
   x = 1 / 0
except Exception as e:
   print(e)
finally:
   print(e)
   del x

上述代码的运行结果如下:

integer division or modulo by zero
del x

我们来看一看 x 是否被删除:

>>> x
Traceback (most recent call last):
 File "test_search.py", line 1, in <module>
   print(x)
NameError: name 'x' is not defined

当然,在应用里面可以将上面的各个句子综合起来使用,写成下面这样:

try:
   do something

except:
   do something

else:
   do something
   
finally:
   do something

写在最后

当你在运行程序的时候遇到异常时,不要慌张,这个其实是好事情,是 Python 在帮助你修改错误。只要你认真的阅读异常信息,再用我们之前学过的 dir(),help() 或官方文档,搜索工具等来协助,就一定会解决问题。


用户评论