【五】持久储存
程序产生数据
很少会有程序从⼀个磁盘⽂件读取并处理数据后就把处理后的数据丢掉。通常情况下,程序会保存所处理的数据,将输出显示在屏幕上,或者通过⽹络传输数据。
将文件中的内容分别储存到2个不同的list中
""" 将文件中的内容分别读取到不同的list中 """ In [7]: cat talk.txt #文件内容 man:hi other:hello man:my name is man other:what? man:year,man is my name,hah other:okay,so cool man:i think so man:and you? other:best man:year other:bye man:bye In [8]: man=[] #创建2个空列表 In [9]: other=[] In [11]: try: ...: data=open("talk.txt") #打开文件,默认为读取r ...: for each_line in data: ...: try: ...: (role,line_spoken)=each_line.split(":",1) #分割每一行的内容 ...: line_spoken=line_spoken.strip()#将去除空白符后的字符在赋给自身。strip()方法是从字符串中去除不想要的空白符 ...: if role=="man": ...: man.append(line_spoken) ...: elif role=="other": ...: other.append(line_spoken) ...: except ValueError: ...: pass ...: data.close() ...: except IOError: ...: print("the datafile is missing") ...: print(man) ...: print(other) ...: ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye'] ['hello', 'what?', 'okay,so cool', 'best', 'bye'] In [12]: man Out[12]: ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye'] In [13]: other Out[13]: ['hello', 'what?', 'okay,so cool', 'best', 'bye']
以写模式写入文件
#格式: out=open("data.out","w") out.write("test") #或者 print("test",file=out) out.close()
将上个代码中的man和other中的数据分别保存到man_data.txt和other_data.txt。这个两个数据文件打开后都要将其关闭,另外还要使用try/except来保护代码避免IOError
# 将man和other中的内容分别保存到man_data.txt/other_data.txt中 In [14]: man #man的内容 Out[14]: ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye'] In [15]: other #other的内容 Out[15]: ['hello', 'what?', 'okay,so cool', 'best', 'bye'] In [16]: try: ...: man_file=open("man_data.txt","w") #打开文件 ...: other_file=open("other_data.txt","w") ...: man_file.write(str(man)) #将man中的内容写入到man_data.txt中 ...: other_file.write(str(other)) ...: man_file.close() #关闭连接 ...: other_file.close() ...: except IOError: ...: print('file error') ...: In [17]: ll total 1192 -rw-------. 1 root 1223 May 17 23:29 anaconda-ks.cfg -rw-r--r--. 1 root 92 Jun 20 00:34 man_data.txt -rw-r--r--. 1 root 295 May 23 05:13 min_max.py -rw-r--r--. 1 root 49 Jun 20 00:34 other_data.txt -rw-r--r--. 1 root 1197370 Nov 6 2016 pip-9.0.1.tar.gz -rw-r--r--. 1 root 163 Jun 19 23:46 talk.txt In [18]: cat man_data.txt ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye'] In [19]: cat other_data.txt ['hello', 'what?', 'okay,so cool', 'best', 'bye']
如果在写入文件中的过程中发生异常,就无法关闭连接。如下图:
so,我们只能用finally来扩展try。
用finally来扩展try
改进代码,如下:
In [20]: try: ...: man_file=open("man_data.txt","w") ...: other_file=open("other_data.txt","w") ...: man_file.write(str(man)) ...: other_file.write(str(other)) ...: except IOError: ...: print('file error') ...: finally: #一定会执行 ...: man_file.close() ...: other_file.close()
有一种异常情况,假如我们在打开文件的时候就error了,那最后的finally中的关闭连接怎样close()呢?
In [22]: try: ...: man_file=open("man_data.txt","w") ...: other_file=open("other_data.txt","w") ...: man_file.write(str(man)) ...: other_file.write(str(other)) ...: except IOError as err: ...: print('file error'+str(err)) #将错误信息打印出来,需要转为str ...: finally: #如果Python在这些名字空间找不到 man_file,它将放弃查找并引发一个 NameError 的异常,同时传 递 There is no variable named 'x' 这样一条信息。 #象Python中的许多事情一样,名字空间在运行时直接可以访问。局部名字空间可以通过内置的 locals 函数来访问 ...: if 'man_file' in locals(): #判断man_file是否在命名空间中,若存在,则关闭连接 ...: man_file.close() ...: if 'other_file' in locals(): ...: other_file.close()
用with处理文件
In [24]: try: ...: with open("man_data.txt","w") as f: ...: f.write(str(man)) ...: with open("other_data.txt","w") as c: ...: c.write(str(other)) ...: except IOError as err: ...: print("file error"+str(err)) ...: In [25]: cat man_data.txt ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye'] In [26]: cat other_data.txt ['hello', 'what?', 'okay,so cool', 'best', 'bye']
使用pickle持久化对象
python的pickle模块实现了基本的数据序列和反序列化。通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。
使用dump保存数据,修改上述代码:
In [27]: import pickle 导入pickle模块 In [28]: try: #使用with一次性打开2个文件 #注意:wb,b为二进制文件 ...: with open('man_data.txt','wb')as man_file,open('other_data.txt','wb')as other_file: ...: pickle.dump(man,man_file) ...: pickle.dump(other,other_file) ...: except pickle.PickleError as err: ...: print('file error'+str(err)) ...: In [29]: cat man_data.txt #结果为乱码,因为是二进制文件 (XhiqX+y +a+e i_ +a+-Xyea_,+a+ i_ +y +a+e,hah-X i +hi++ _--a+d y-+?-Xyea_-Xbye-e.
使用load从文件中恢复数据
In [3]: new_man=[] In [4]: man_file=open("man_data.txt",'rb') In [6]: import pickle In [7]: new_man=pickle.load(man_file) In [8]: new_man Out[8]: ['hi', 'my name is man', 'year,man is my name,hah', 'i think so', 'and you?', 'year', 'bye']