11.文件和异常

11.文件和异常

在Python中实现文件的读写操作通过内置的open函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。

读写函数:

操作模式具体含义
‘r’读取(默认)
‘w’写入(会先截断之前的内容)
‘x’写入,如果文件已经存在会发生异常
‘a’追加,讲内容写入到已有文件的末尾
‘b’二进制模式
‘t’文本模式(默认)
‘+’更新(既可以读又可以写)

读写文本文件

读取文本文件时,需要在使用open函数时指定好带路径的文件名(可以使用相对路径或绝对路径)并将文件模式设置为‘r’(如果不指定,默认值也是’r’),然后通过encoding参数指定编码(如果不指定,默认值为None,那么在读取文件时使用的是操作系统默认的编码),如果不能保证保存文件时使用的编码方式与encoding参数指定的编码方式是一致的,那么就可能因无法解码字符而导致读取失败。

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
def main():
f = None
try:
f = open('致橡树.txt','r',encoding='utf-8')
print(f.read())
except FileNotFoundError:
print('无法打开指定的文件!')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误!')
finally:
if f:
f.close()

可以用with代替finally
# def main():
# try:
# with open('致橡树.txt','r',encoding='utf-8') as f:
# print(f.read())
# except FileNotFoundError:
# print('无法打开指定的文件!')
# except LookupError:
# print('指定了未知的编码!')
# except UnicodeDecodeError:
# print('读取文件时解码错误!')

if __name__ == '__main__':
main()

通过for-in循环逐行读取或者用readline方法将文件按行读取到一个列表容器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import time

def main():
# 一次性读取整个文件内容
with open('致橡树.txt','r',encoding='utf-8') as f:
print(f.read())
# 通过for-in循环逐行读取
with open('致橡树.txt',mode='r') as f:
for line in f:
print(line,end='')
time.sleep(0.5)
print()
# 读取文件按行读取到列表中
with open('致橡树.txt') as f:
lines = f.readlines()
print(lines)

if __name__ == '__main__':
main()

文本信息写入文件文件使用open函数,指定好文件名并将文件模式设置’w’即可。如果需要对文件内容进行追加式写入,应该将模式设置为’a’。如果要写入的文件不存在会自动创建文件而不是引发异常。下面的例子演示了如何将1-9999之间的素数分别写入三个文件中(1-99之间的素数保存在a.txt中,100-999之间的素数保存在b.txt中,1000-9999之间的素数保存在c.txt中)。
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
31
32
33
34
from math import sqrt

def is_prime(n):
"""判断素数"""
assert n > 0
for factor in range(2,int(sqrt(n)) + 1):
if n % factor == 0:
return False
return True if n != 1 else False

def main():
filenames = ('a.txt','b.txt','c.txt')
fs_list = []
try:
for filename in filenames:
fs_list.append(open(filename,'w',encoding='utf-8'))
for number in range(1,10000):
if is_prime(number):
if number < 100:
fs_list[0].write(str(number)+'\n')
elif number < 1000:
fs_list[1].write(str(number) + '\n')
else:
fs_list[2].write(str(number) + '\n')
except IOError as ex:
print(ex)
print('写文件时发生错误!')
finally:
for fs in fs_list:
fs.close()
print('操作完成!')

if __name__ == '__main__':
main()

读写二进制文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
复制图片文件功能
def main():
try:
with open('guido.jpg','rb') as fs1:
data = fs1.read()
print(type(data)) #<class 'bytes'>
with open('优秀.jpg','wb') as fs2:
fs2.write(data)
except FileNotFoundError as e:
print('指定的文件无法打开.')
except IOError as e:
print('读写文件时出现错误.')
print('程序执行结束.')
if __name__ == '__main__':
main()

读写JSON(JavaScript Object Notation)文件

1
2
3
4
5
6
7
8
9
10
11
{
"name": ’张三‘,
"age": 35,
"qq": 957658,
"friends": ['王大锤','白元芳'],
"cars": [
{"brand": 'BYD', 'max_speed':180}
{"brand": 'Audi','max_speed':280},
{"brand": 'Benz','max_speed':320}
]
}

JSON跟Python中字典其实是一样一样的,事实上JSON的数据类型和Python的数据类型是很容易找到对用关系的

JSONPython
objectdict
arraylist
stringstr
number(int/real)int/float
true/falseTrue/False
nullNone
PythonJSON
dictobject
list,tuplearray
strstring
int,float,int-&float-derived Enumsnumber
True/Flasetrue/false
Nonenull