Python初入门(四)(Head First Python 第四章 数据保存到文件)

来源:互联网 发布:免费外汇交易软件 编辑:程序博客网 时间:2024/06/05 10:28

程序生成数据

我们先处理数据,看看谁对谁说了什么。

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!')print(man)print(other)

str.strip([chars])——strip() 方法用于移除字符串头尾指定的字符(默认为空格)。与java类似。

其中的elif为else if的简写。


得到man和otherman说的话后,我们想将他们的话分别存到两个文件中,这个时候就需要写操作了。

使用open()BIF打开磁盘文件时,可以制定使用什么模式访问。默认地,open()使用模式r表示读,所以不需要专门制定r模式。要打开一个文件完成写,需要使用模式w。

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!')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)except IOError:    print('File error.')finally:     man_file.close()     other_file.close()

可以看到
man_file = open(‘man_data.txt’, ‘w’)中,man_file是数据文件对象,‘man_data.txt’是所写文件的文件名,w代表写模式。

默认地,print()BIF显示数据时会使用标准输出(通常是屏幕).要把数据写至一个文件,需要使用file参数来指定所使用的数据文件对象:
print(man, file=man_file),其中man表示写至文件的内容,man_file表示所写数据文件对象。file参数控制将数据发送/保存到哪里。

完成工作时记得close,确保所有数据都写至磁盘,这成为刷新输出(flushing)。这一点和java的I/O流是一样的。

可以发现,这里使用了try/except/finally机制,类似于java中的try/catch/finally,无论有无捕捉到异常,finally中的代码都会执行,这就确保了文件关闭代码一定执行,减少了数据破坏错误的可能性。


错误类型

运行时出现一个错误时,Python会产生一个特定类型的异常(如IOError,ValueError等)。另外,Python会创建一个异常对象,它会作为一个参数参入except代码组。

try:    data=open('missing.txt')    print(data.readline(),end='')except IOError as err:    print('File error'+str(err))finally:    if 'data' in locals():        data.close()

在这里,我们尝试打开一个并不存在的文件missing.txt,此时Python解析器会返回error。

except IOError as err:
print(‘File error’+str(err))
产生一个异常并有except组处理时,Python解释器将一个异常对象传入这个except组,并使用as关键字赋至一个标识符。这一点和java中的catch(IOException e)是十分相似的。

而str()方法将异常对象转换(或强制转换)为字符串。

同时,我们看到finally中,locals()BIF会返回当前作用域中定义的所有名的一个集合。如果data在这个集合中时,才会调用close()。


用with处理文件

由于处理文件时try/except/finally模式相当常用,所以Python提供了一个语句来抽象出相关的一些细节。对文件使用with语句时,可以大大减少编写的代码量。因为有了with语句就不再需要包含一个finally组来处理文件的关闭,即妥善关闭一个可能打开的数据文件。

来看下面例子:
使用try/except/finally模式

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)except IOError as err:    print('File error.'+str(err))finally:    if 'man_file' in locals():        man_file.close()    if 'other_file' in locals():        other_file.close()

使用with语句

try:    with open('man_data.txt','w') as man_file:        print(man, file=man_file)    with open('other_data.txt','w') as other_file:        print(other, file=other_file)except IOError as err:    print('File error.'+str(err))

还可以合并到一个with语句中

try:    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)except IOError as err:    print('File error.'+str(err))

使用with时,不再需要操心关闭打开的文件,因为Python解释器会自动为你考虑这一点。with语句利用了一种名为上下文管理协议(context management protocol)的Python技术。


默认格式对文件并不合适

这里我们可以使用前面创建的print_lol()函数,来将数据项一行一行的输出。
需要对该函数进行改动:

import sysdef print_lol(the_list,indent=False,level=0,fh=sys.stdout):        for each_item in the_list:                if isinstance(each_item,list):                        print_lol(each_item,indent,level+1,fh)                else:                        if indent:                                for tab_stop in range(level):                                        print("\t",end='',file=fh)                        print(each_item,file=fh)

标准输出(standard output)这是使用”print()”BIF时代码写数据的默认位置。这通常是屏幕。在Python中,标准输出是指”sys.stdout”,可以从标准库的”sys”模块导入。

第二个参数indent控制是否显示在屏幕上,默认是False。

第三个参数level(默认值为0)用来判断是否嵌套。

第四个参数fh=sys.stdout,用来标识将把数据写入哪个位置。一定要为这个参数提供一个缺省值sys.stdout,这样如果调用这个函数时没有只id那个文件对象则会依然写至屏幕。

而输出数据到文件的代码改为:

import nesterman=[]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!')try:    with open('man_data.txt','w') as man_file,open('other_data.txt','w') as other_file:        nester.print_lol(man, fh=man_file)        nester.print_lol(other, fh=other_file)except IOError as err:    print('File error.'+str(err))

这时可以看到输出是符合我们的要求了这里写图片描述


腌制数据

使用pikcle的通用文件I/O才是上策

Python提供了一个标准库,名为pickle(腌制),.它可以保存和加载几乎任何Python数据对象,包括列表。
一旦把数据”腌制”到一个文件,它将会永久存储,可以在以后某个日期/时间读入另外一个程序。当然,也可以把”腌制”的数据存储到磁盘上,放在数据库中,或者通过网络传到另外一台计算机中。
将这个过程反过来,将持久存储的腌制数据解除腌制,在Python的内存中庸原来的形式重新创建数据。

腌制
将数据对象保存到一个持久存储中的过程。

解除腌制
从持久存储中恢复一个已保存的数据对象的过程。

使用pickle很简单,只需导入所需的模块pickle,然后使用dump保存数据,以后某个时间使用load()回复数据。处理腌制数据的唯一要求是,必须以二进制访问模式打开这些文件。

pickle.dump()函数将数据保存到磁盘。
pickle.load()函数从磁盘恢复数据。

import pickleman = []other = []try:    data = open('sketch.txt')    for each_line in data:        try:            (role, line_spoken) = each_line.split(':')            line_spoken = line_spoken.strip()            if role == 'Man':                man.append(line_spoken)            elif role == 'Other Man':                other.append(line_spoken)            else:                pass        except ValueError:            pass    data.close()except IOError:    print('The datafile is missing!')try:    with open('man_data.txt', 'wb') as man_file, open('other_data.txt', 'wb') as other_file:        pickle.dump(man, file=man_file)        pickle.dump(other, file=other_file)except IOError as err:    print('File error: ' + str(err))except pickle.PickleError as perr:    print('Pickling error: ' + str(perr))

可以发现open的模式为wb,其中w代表写,b表示Python以二进制打开数据文件。

pickle.dump(man, file=man_file)——用dump保存man到man_file对象中。

腌制或者解除数据时如果出现错误,pickle模块会产生一个PickleError类型的异常。

打开文件后发现存储的看起来是乱码
这里写图片描述
Python为了更高效完成腌制,pickle模块使用了一种定制的二进制格式(这称为它的协议)。

要想得到原本数据,需要解除腌制,这个时候要使用pickle.load()
这里写图片描述
这里open模式为rb

注意,访问列表的最后一个数据项,下标应该为-1.

不难发现,pickle和java中的字节输入输出流是相似的。