程序处理文件以后一般不会丢弃而是存储在磁盘
修改上一章的代码满足一下要求
1,创建一个空列表为man
2,创建一个空列表为other
3,增加一行代码,删除line_spoken中的空格及回车
4,给出条件和代码,根据role值将line_spoken增加到适当的列中
5,在屏幕上面输出man和other列表
vim sketch-1.py
man = [] other = [] #新建两个空列表 data = open('sketch.txt') #打开文件 for each_line in data: #按行迭代 try: #和except一起忽略代码的指定错误 (role,line_spoken) = each_line.split(':',1) #使用符号:分割列成为一个元祖赋值给role和line_spoken分别代表人物和说的话 line_spoken = line_spoken.strip() #使用strip()函数去掉空格和回车 if role == 'Man': #判断假如人物是Man,将他说的话用apppend方法追加到man列表 man.append(line_spoken) else: other.append(line_spoken) #将其他人说的话追加到other列表 except ValueError: pass print man print other data.close()
运行结果
以上只是把两个说的户输出到屏幕,下面修改代码使其存储到文件中
vim sketch-2.py
#!/usr/bin/python # -*- coding:utf-8 -*- man = [] other = [] #新建两个空列表 data = open('sketch.txt') #打开文件 for each_line in data: #按行迭代 try: #和except一起忽略代码的指定错误 (role,line_spoken) = each_line.split(':',1) #使用符号:分割列成为一个元祖赋值给role和line_spoken分别代表人物和说的话 line_spoken = line_spoken.strip() #使用strip()函数去掉空格和回车 if role == 'Man': #判断假如人物是Man,将他说的话用apppend方法追加到man列表 man.append(line_spoken) else: other.append(line_spoken) #将其他人说的话追加到other列表 except ValueError: pass
data.close() #print man #print other try: man_file = open('man_data.txt','w') other_file = open('other_data.txt','w') # print (man,file=man_file) # print (other,file=other_file) #按书里的这语法会报错可能是python3的语法 man_file.write(' '.join(man)) other_file.write(' '.join(other)) #写文件,需要是字符串格式使用join转换 man_file.close() other_file.close() except IOError: print ('File error') ~
在当前文件夹生成两个文件记录内容
man_data.txt
other_data.txt
PS:如果只是从文件读取数据得到一个IOError确实很烦人,不过还不算危险,因为数据还在文件中,只是得到这些数据有些麻烦
向文件写数据就完全不一样了,如果文件在关闭前出现一个IOError,所写的数据可能会被破坏,而且只有在这种情况发生了才知道
否则根本无法了解这一点。假如以上代码
other_file.write(' '.join(other))出现问题一下的关闭操作不会执行,这里有一个策略保证无论是否出现错误都能运行某些代码
#!/usr/bin/python # -*- coding:utf-8 -*- man = [] other = [] #新建两个空列表 data = open('sketch.txt') #打开文件 for each_line in data: #按行迭代 try: #和except一起忽略代码的指定错误 (role,line_spoken) = each_line.split(':',1) #使用符号:分割列成为一个元祖赋值给role和line_spoken分别代表人物和说的话 line_spoken = line_spoken.strip() #使用strip()函数去掉空格和回车 if role == 'Man': #判断假如人物是Man,将他说的话用apppend方法追加到man列表 man.append(line_spoken) else: other.append(line_spoken) #将其他人说的话追加到other列表 except ValueError: pass data.close() #print man #print other try: man_file = open('man_data.txt','w') other_file = open('other_data.txt','w') # print (man,file=man_file) # print (other,file=other_file) #按书里的这语法会报错可能是python3的语法 man_file.write(' '.join(man)) other_file.write(' '.join(other)) #写文件,需要是字符串格式使用join转换 except IOError: print ('File error') finally: man_file.close() other_file.close() #不管是否出现错误都会执行关闭
不论出现什么情况finally下的代码都会执行。可以减少数据破坏的可能性,这是一个很大的改进,可以确保文件妥善的关闭
知道错误类型还不够
出现文件IO错误时候,代码一般会先一个file error,太过于一般化了因为有几种可能
1,文件无法打开
2,可以打开但是无法x写入
3,可能是一个权限错误,或者磁盘满了
谁知道呢 ,看起来python解释器知道,运行时出现错误python会产生一个特定类型的异常,会创建一个异常对象,它会作为一个参数传递
except代码组
看一下例子,试着打开一个不存在的文件,File error是错误消息,NameError这个异常导致了代码
崩溃,文件不存在就不能在数据对象调用close()方法。一种简单的修正方法是对finally组增加一个
简单的测试,尝试调用close()之前先查看data名是否存在。locals()BIF会返回当前作用域中定义
的所有名的一个集合,只有在安全时候才调用close()
这里会在locals()BIF返回的集合中搜索字符串data如果有代表文件安全打开可以调用close,所以只提示是File error错误
不过还是不清楚到底什么导致了这个错误
产生的异常由except组处理时,Python解释器将一个异常对象传入这个except组。只需要做一个很小的修改就可以在代码中使用这个异常
vim sketch-3.py
try: data = open('miss.txt') print data.readline(), except IOError as err: #为异常对象取一个名 print 'File error' + err #作为错误消息输出 finally: if 'data' in locals(): data.close()
运行还是报错TypeError
是以为异常对象和字符串不兼容,使用str()转换成字符串
#!/usr/bin/python # -*- coding:utf-8 -*- try: data = open('miss.txt') print data.readline(), except IOError as err: #为异常对象取一个名 print 'File error' + str(err) #作为错误消息输出 finally: if 'data' in locals(): data.close()
运行输出了正确的错误提示
用with处理文件
由于处理文件时使用模式try/except/finally模式相当有用,所以python提供了一个语句抽象
出相关的一些细节。对文件使用with语句可以大大减少需要编写的代码量,因为有了with语句
不再需要包含一个finally组来处理文件的关闭
vim sketch-5.py
#!/usr/bin/python # -*- coding:utf-8 -*- man = [] other = [] #新建两个空列表 #data = open('sketch.txt') #打开文件 with open('sketch.txt') as data: for each_line in data: #按行迭代 try: #和except一起忽略代码的指定错误 (role,line_spoken) = each_line.split(':',1) #使用符号:分割列成为一个元祖赋值给role和line_spoken分别代表人物和说的话 line_spoken = line_spoken.strip() #使用strip()函数去掉空格和回车 if role == 'Man': #判断假如人物是Man,将他说的话用apppend方法追加到man列表 man.append(line_spoken) else: other.append(line_spoken) #将其他人说的话追加到other列表 except ValueError: pass data.close() #print man #print other try: # man_file = open('man_data.txt','w') # other_file = open('other_data.txt','w') with open('man_data.txt','w') as man_file,open('other_data.txt','w') as other_file: # print (man,file=man_file) # print (other,file=other_file) #按书里的这语法会报错可能是python3的语法 man_file.write(' '.join(man)) other_file.write(' '.join(other)) #写文件,需要是字符串格式使用join转换 except IOError: print ('File error') #finally: #不需要执行关闭 # man_file.close() # other_file.close()
删除之前生成的文件man_data.txt和other_data.txt运行新代码,效果和之前的是一样的
下面向之前学习的print_lol函数增加第四个参数,用来标识把数据写在那个位置.一定要为这个参数
提供一个缺省值sys.stdout,这样如果调用这个函数没有指定的文件对象则会依然显示在屏幕
vim 128.py
#!/usr/bin/python # -*- coding:utf-8 -*- import sys man = [] other = [] try: data = open('sketch.txt') for each_line in data: try: (role,line_spoken) = each_line.split(':',1) line_spoken = line_spoken.strip() if role == 'Man': man.append(line_spoken) elif role == 'Other Man': other.append(line_spoken) except ValueError: pass data.close() except IOError: print ('The datafile is missing!') def print_lol(the_list,indent=False,level=0,fn=sys.stdout): for each_item in the_list: if isinstance(each_item,list): print_lol(each_item,indent,level+1,fn) else: if indent: for tab_stop in range(level): print(" ",end='',file=fn) print (each_item,file=fn) try: with open('man_data.txt','w') as man_file: print_lol(man,fn=man_file) #python3.5的写文件方法,2.7不适用 with open('other_data.txt','w') as other_file: print_lol(other,fn=other_file) except IOError as err: print('File error:' + str(err))
PS:这个为后来补充的按照书里python3的语法写的
执行这个脚本生成的文件内容如下
"腌制"数据
Python提供了一个标准库,名为pickle他可以保存和加载几乎任何Python数据对象,包括列表
使用pickle很简单,只需要导入需要的模块,然后使用dump()保存数据,在以后的某个时间
使用load()恢复数据。出来数据的唯一要求必须以二进制模式打开文件
vim sketch-6.py
#!/usr/bin/python # -*- coding:utf-8 -*- import pickle #导入模块 with open('mydata.pickle','wb') as mysavedata: #b参数以二进制方式打开 pickle.dump([1,2,'there'],mysavedata) #保存时刻 with open('mydata.pickle','rb') as myrestoredata: a_list = pickle.load(myrestoredata) #恢复数据赋值给a_list print(a_list)
输出
[root@VPN chapter3]# python sketch-6.py
[1, 2, 'there']