第四章:持久存储

程序处理文件以后一般不会丢弃而是存储在磁盘

修改上一章的代码满足一下要求

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']

原文地址:https://www.cnblogs.com/minseo/p/6750390.html