Python之文件与异常

过完年了,新的一年希望能找份理想的工作,好了开始正题,今天读的是Python中的文件和异常

Python是如何从文件读取数据的呢,先看一段代码:

1
2
3
4
file = open('a.txt')
#Todo something with the file
...
file.close()

看完上面这段代码就基本明白,Python是通过open()这个BIF来和文件交互,结合for语句使用,就很容易实现从文件中读取数据了。

Python中和读取文件相关的几个方法的基本功能如下所示:

open()

BIF打开一个磁盘文件,创建一个迭代器从文件读取数据,一次读取一行

readline()

从一个打开的文件读取一行数据

seek()

可以用来将文件‘退回’到起始位置

close()

关闭一个之前打开的文件

split()

可以将一个字符串分解为一个子字串列表,可以指定一个最大分割数来限定最多分割为几部分,如果没有指定分隔符的话,默认以空格作为分隔符进行分割

find()

在一个字符串中查找一个特定子串,找到的话返回特定子串的起始位置,找不到返回-1

先看一下下面这段Python代码(注意:该Python文件的要和sketch.txt这一个目录)

1
2
3
4
5
6
7
8
data = open('sketch.txt')
for each_line in data:
(role,line_spoken) = each_line.split(':')
print(role,end='')
print(' said: ',end='')
print(line_spoken,end='')

data.close()

这段代码很简单,就是读取文件sketch.txt里面的内容,将每行以:分割,然后进行格式化输出,但是事实上这段代码是不完善的,因为如果sketch.txt里面某一行没有:字符亦或者某一行里面不止一个:字符,程序执行过程中都会出现ValueError错误,为了让程序变的更健壮,我们改一下,下面是2.0版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
data = open('sketch.txt')

for each_line in data:
if not each_line.find(':') == -1:
(role,line_spoken) = each_line.split(':',1)
print(role,end='')
print(' said: ',end='')
print(line_spoken,end='')

data.close()
```
2.01.0的基础上有两个改动:
<!--more-->
* 判断某一个有没有:这个符号,有的话再分割,防止某一行没有:而出错
* split传入第二个可选参数maxsplit(最大分割数),限制只分为两部分,防止:过多而出错

现在看上去程序是没有什么错误了,也能够正常输出了。但是问题还是来了,你会发现这样做的话如果后面我又想以,或者其他字符作为分隔符,改动的就多了,而且if语句感觉好像也很别扭,那么有没有更好的解决办法呢?我们一起看看3.0版本
```Python
data = open('sketch.txt')

for each_line in data:
try:
(role,line_spoken) = each_line.split(':',1)
print(role,end='')
print(' said: ',end='')
print(line_spoken,end='')
except:
pass

data.close()

有其他编程语言经验的一眼就看出来了,这不是异常捕获呢,对,这就是Python的异常捕获机制,简称try/except机制,try:后面跟你可能会抛出运行时错误的代码,except:后面跟错误恢复代码,上面是直接跟一个pass,相当于空语句,什么都不做。

这样一来,3.0版本的不但可以正常运行,而且兼容性还比较高,代码逻辑简单,是不错的选择。这个会不会还有其他错误呢,细心观察会发现open() BIF这里,如果文件不存在,会抛出IOError错误。为了解决错误,我们可以选择增加逻辑判定sketch.txt是否存在或者再加一层异常处理,前面已经对比过,增加异常处理相对比增加代码逻辑要好一些,所以我们选择再增加一层异常处理。

另一方面我们捕获异常的时候使用的是except:这种一般法的方式,这样无论什么样的异常或者错误都会被忽略,这并不是我们要的,因为我们知道现在会出现的错误只有外层open的IOError和字符串截取可能发生的ValueError这两种错误,我们只想针对这两种错误捕获异常,而不是忽略任何错误,这样不利于我们分析问题。

综合上面两点,最终版4.0如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try:
data = open('sketch.txt')

for each_line in data:
try:
(role,line_spoken) = each_line.split(':',1)
print(role,end='')
print(' said: ',end='')
print(line_spoken,end='')
except ValueError:
pass

data.close()

except IOError:
print('The data file is missing!')

tips:

Python中不可改变的常量列表称为元组(tuple)。一旦将列表数据赋值至一个元组,就不能再改变,元组是不可改变的