小言_互联网的博客

深入理解python异常处理(主要是利用try语句去捕获异常,那么什么是try语句,try语句怎么用,try语句有哪些功能。还会总结文件处理的方法)

318人阅读  评论(0)

一.什么是异常

我们需要明白的是异常的发生不是因为我们代码写错了,我们的代码是可以编译的,但是在运行时产生了一个错误,这个错误是一个异常情况,计算机不能处理这个异常情况,就产生了一个异常。
总结一下异常发生:1.不是代码的问题。 2.比如想要打开的文件不存在,想要处理的问题输入了一个异常值等等都会产生一个异常。

二.如何处理异常

对于异常的处理一般有两种方法。
第一种方法:增加新的逻辑,去处理这个异常,比如打开的文件不存在,我们就增加一个判断语句,判断文件是否存在。但是如果有更多的问题出现,那么就需要增加更多的逻辑,我们可以知道这种方法并不高明。
第二种方法:使用try语句处理异常,事实上,python允许我们在异常发生时捕获异常,这么就给我们提供了一个机会,可以从这个错误中恢复,最重要的是可以避免崩溃,这样在面对大多数运行时错误我们的程序都是健壮的。
那么不知道你们有没有这样的疑问,为什么try语句就能做到捕获异常,还能从这个错误中恢复呢,这是因为在异常控制流期间,python会先尝试运行我们的代码,如果我们的代码发现有问题,就会执行恢复代码,然后继续正常执行我们的代码
下面用图来比较一下正常控制流和异常控制流的区别:
正常控制流:(发生异常,代码就不能继续执行)

异常控制流:(发生异常,捕获异常,执行恢复代码,异常得到处理,继续执行)

三.try…except机制:


try语句允许错误发生,如果针对每一个可能的错误都编写代码,这无疑是一个巨大的工程,而使用try语句,我们操心的更少,编写代码的任务也会轻松很多。

四.下面用一个读取文件的例子去使用try语句。

我们要读取一个文件,文件内容如下:
python读取文件的机制是按行读取的,一次会达到一个数据行。

data =  open('test.txt')
for each in data:
    (role, line_spoken) = each.split(':', 1)
    print(role, end='')
    print('said:', end='')
    print(line_spoken, end='')
data.close()

1.我们没有创建test.txt文件,于是就出现了一个异常:No su’ch file or directory

2.使用try…except.
注意上面写的要保护的代码,我们要找出要保护的代码,在这里就是所有的代码。
修改代码如下:

try:
    data =  open('test.txt')
    for each in data:
       (role, line_spoken) = each.split(':', 1)
       print(role, end='')
       print('said:', end='')
       print(line_spoken, end='')
    data.close()
except IOError as err:
    print("File error:" + str(err))

运行,可以看到代码正常执行了,并且输出了except的内容(处理特定异常)
这里的as 是给异常对象取一个名字,str(err),把异常对象强制转换成字符串。不然会发生TypeError.

但是这里我们需要注意的一点是如果我们只是读取一个文件,发生IOError确实很烦人,不过一般还不算危险,因为我们的数据还在文件中,向文件中写数据就完全不同了,如果在文件关闭前需要处理一个IOError,所写的数据有可能被破坏
例子如下:

test = []
try:
    data=open('test.txt')
    for each in data:
       test.append(each)
    data.close()
except IOError as err:
    print("File error:" + str(err))


try:
    test_file =  open('test_data.txt','w')
    print(test, file=test_file)
    test_file.close()
except IOError as err:
    print("File error:" + str(err))

先讲一下上面的涉及知识点:
1.open函数常用形式open(file, mode=‘r’)。
2.open函数默认使用模式 r 表示读。mode是可选参数,但在函数中给参数赋一个值,该参数变为可选参数。w表示只用于写,wb以二进制格式打开一个文件只用于写入。
3.file,文件路径,必选路径(可以是相对路径和绝对路径),绝对路径就是在写路径时把位置都写清楚,如下写法是绝对路径:data=open(‘C:/Users/ASUS/Desktop/test.txt’)(注意在windows系统下,是正斜杆,不是反斜杠)
data=open(‘test.txt’),该写法是相对路径,对于相对路径,如果前面一个目录也没有,需要让test.txt与test.py在一个目录下才可以这样写,也可以在test.py当前目录下再创一个文件夹,把test.txt放进该文件夹中,如创建test目录,则写法变为 data=open(‘test/test.txt’),相对路径只有这两种,要么在同一个目录,要么在.py文件目录下的子目录中。
4.使用print把指定的列表写入指定的文件中。
5.写入效果如下,是一个列表。

6.open函数并非只能访问文本文件,open可以访问任何形式的文件,在访问非文本格式文件(二进制文件)的时候,访问模式通常加上‘b’(即二进制模式:‘rb’或‘wb’),但并不必须,依情况而定
我上面说了那么多其实就是想引入一个finally:

想一下,如果发生上面的情况该怎么办,这种情况文件也没有关闭,并且数据也有可能被破坏。
这里需要一种策略,保证不论是否发生IOError都会运行某些代码,在代码上下文,我们希望不论发生什么都要确保关闭文件。
于是我们可以使用finally.
代码如下:

用finally扩展try:

test = []
try:
    data=open('C:/Users/ASUS/Desktop/test.txt')
    for each in data:
       test.append(each)
    data.close()
except IOError as err:
    print("File error:" + str(err))


try:
    test_file =  open('test_data.txt','w')
    print(test, file=test_file)
except IOError as err:
    print("File error:" + str(err))
finally:
    test_file.close()

于是无论如何文件都会关闭了,finally的作用就是这样。通过把文件关闭代码移入到finally组中,可以减少数据被破坏的可能性。
那么会不会有其他错误呢,如果打开一个不存在的文件,在finally中将文件关闭会发生什么?
修改代码如下:

test = []
try:
    data=open('miss.txt')
    for each in data:
       test.append(each)
    data.close()
except IOError as err:
    print("File error:" + str(err))


try:
    test_file =  open('test_data.txt','w')
    print(test, file=test_file)
except IOError as err:
    print("File error:" + str(err))
finally:
    test_file.close()

可以发现这个错误‘data’ is not defined.

这是因为文件不存在,数据对象未创建,这样就不可能在数据对象上调用close方法,那么我们又该怎么办呢?
修改代码如下:

test = []
try:
    data=open('miss.txt')
    for each in data:
       test.append(each)
    data.close()
except IOError as err:
    print("File error:" + str(err))


try:
    test_file =  open('test_data.txt','w')
    print(test, file=test_file)
except IOError as err:
    print("File error:" + str(err))
finally:
    if 'data' in locals():
        data.close()

locals函数返回当前作用域中定义的所有名的一个集合。
这样就没有其他的异常了。只会显示错误信息。

说了那么多,终于说完了,既然这么麻烦,打开文件有没有什么更好的办法。
当然有,可以使用with处理文件。

test = []
try:
    data=open('miss.txt')
    for each in data:
       test.append(each)
    data.close()
except IOError as err:
    print("File error:" + str(err))


try:
    with open('test_data.txt','w') as test_file:
        print(test, file=test_file)
except IOError as err:
    print("File error:" + str(err))

上面的代码跟使用finally的功能一样,当然with的用法很多,需要单独拿出来总结。

五.try语句的其他各种形式:

当然except可以写多个,格式如下:

try:
   要保护的代码。
except <异常名字>:
   错误恢复代码(如果发生这个异常就执行该except后的错误恢复代码)
except <异常名字>:
   错误恢复代码(如果发生这个异常就执行该except后的错误恢复代码)
else:
   没有异常运行这断代码,可写可不写,想写就写。

如果except不带任何异常类型,就会捕获所有异常。但是我们并不推荐这么做,因为不知道异常类型。

try:
   要保护的代码
except:
    错误恢复代码(捕获所有异常)
else:
    没有异常执行这段代码

也可以用相同的except处理多种异常类型

try:
    要保护的代码
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   发生以上多个异常中的一个,执行这段代码
   ......................
else:
    如果没有异常执行这段代码

写法如下:


try:
    要保护的代码
except (IOError, ValueError):
     发生以上多个异常中的一个,执行这段代码  

还有一个知识点就是raise.
我们可以使用raise语句自己触发异常
触发之后后面的语句不会执行,触发之后然后用except捕获相同的异常类型。具体使用就不总结,今天总结太多了。
还有我们需要知道的是一些常用的异常类型,网上有很多,多看一下就熟悉了。

今天的总结就到这,拜拜。
如果有任何错误,欢迎大佬指正,非常感谢。


转载:https://blog.csdn.net/weixin_45290352/article/details/105774582
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场