21 文件操作

Python在一些应用应用例如:机器学习、大数据、深度学习等延伸领域或多或少地或用到一些样例文件,有的是纯文本的有的是用一定的符号例如逗号、分号、冒号等将一条记录的各个字段分割开,这样的存储数据的方式典型的文件类型有csv文件、xml文件等。

21.1 文件的基本操作

Python编程文件读写和其他语言下的文件读写过程和使用的函数基于一样,一般流程是通过open函数打开磁盘上的某个文件,通过这个open函数的返回值来读写文件里的内容,读写完毕后用close函数关闭文件。

打开文件open函数

用open函数访问(打开)磁盘上的物理文件,open函数的参数一般是两个,一个是文件名,一个是读写方式字。 下面以读写机器学习领域内较为经典的数据集鸾尾花数据iris.data 为例打开该文件,程序代码和下载下来的iris.data文件(另存为iris.csv)可以在同一个目录下或处在不同的目录也行,本例两个文件在同一个目录下。

#coding:utf-8
filename = "iris.csv"
fn = open(filename, "r")
print fn
ret = fn.read(10)
print ret
fn.close()

代码里open函数以只读的方式打开了同目录下的iris.csv文件,函数的返回值是fn代表Python打开的这个文件,对磁盘上的iris.csv文件的各项操作都通过fn来进行。

21.2 读文件

Python的文件读相关函数有几个:read、readline以及readlines等。

read函数读若干字节

read函数的作用是读文件里的内容,其参数指定读回的字节数,函数read的返回值是字符串,数据保存在ret这个变量里。程序的最后需要关闭文件,可以通过close函数来关闭python打开的磁盘上的文件。程序执行结果如下:

<open file 'iris.csv', mode 'r' at 0xb74b5180>
5.1,3.5,1.

显示结果第一行是print fn的输出信息,第二行是print ret语句执行结果信息。 有关read函数的帮助可以在交互环境下查看。

>>> help(file.read)
Help on method_descriptor:
read(...)
    read([size]) -> read at most size bytes, returned as a string.    

对于read函数里的size形参,如果文件里可读的数据不够有多少读多少但最多读回size字节数据。如果不指定size,也就是fn.read()那么会读回整个文件的内容,如果文件大小比较小,可以这样用,但是如果是一个巨型文件不建议不指定size的值,否则内存消耗太大!

readline读一行

read函数会读回若干字节的数据或整个文件里的内容,有的时候文件里的数据可能是按行分布的且想读一行再读一行这样不断的去读文件,python提供了readline函数,每次可以从文件里读回一行数据(一直读到本行回车为止)。另外open函数返回值是可以迭代的,这样就可以一行行的读完整个文件。这样的好处是如果文件比较大,可以在小内存计算机上读写大文件的内容。

#coding:utf-8
filename = "iris.csv"
fn = open(filename, "r")
ret = fn.read(10)
print "read(10)", "*" * 10
print ret
print "readline()", "*" * 8
ret = fn.readline()
print ret
print "for v in fn", "*" * 7
print ret
for v in fn:
    print v
fn.close()

程序的执行结果如下所示:

输出结果很奇怪,需要解释。奇怪一:readline函数返回值并不少一整行?为什么?因为readline函数是从当前位置一直读到本行结尾即回车键。在readline之上还有一个read函数读了10字节,那么文件读写位置还在文件的第一行,所以readline只会将第一行到结尾的数据读回,而不会文件的读第二行。奇怪二:打印的"for v in fn *"上边感觉多了一空行?这是什么?原因是print函数执行会自动换行,多出的一空行原因在于readline会读到每行的回车,所以ret里有一个回车,print有一个回车,所以结果就多了一空行。

readlines函数读多行

readlines函数可以从文件当前读写位置开始一值到文件结尾读回多行的文件,每行作为列表里的一项,所以该函数的返回值是列表。

#coding:utf-8
filename = "iris.csv"
fn = open(filename, "r")
ret = fn.read(10)
print "read(10)", "*" * 10
print ret
print "readline()", "*" * 8
ret = fn.readlines()
print ret[:3]
print "for v in fn", "*" * 7
for v in ret:
    print v
fn.close()

程序执行结果如下:

print ret[:3]的输出信息可以看到的确每行最后有回车'\n'。

21.3 读写位置定位

和文件读写位置相关的函数有seek和tell两个函数。

tell函数可以知道当前位置

想知道文件读到那儿了?可以用tell函数。

#coding:utf-8
filename = "iris.csv"
fn = open(filename, "r")
ret = fn.read(10)
print fn.tell()
fn.close()

seek函数调整读写位置

先看看seek的函数seek(offset[, whence]) ,offset是从当前读写位置偏移多少字节,whence有三个值0、1、2。0是默认值意思是从文件开始向文件尾部偏移offset(大于等0),1是从当期位置向文件头偏移offset(可正可负)。而2的意思是从文件尾部开始偏移offset(小于0)。 假设a.txt文件里的内容是"1234567890",通过该文件展示seek函数里的whence形参的含义。

#coding:utf-8
filename = "a.txt"
fn = open(filename, "r")
print "Now at ",fn.tell()
print fn.read(2)
print "Now at ",fn.tell()
fn.seek(3, 0)
print "Now at ",fn.tell()
print fn.read(2)
print "Now at ",fn.tell()
fn.seek(-3, 1)
print "Now at ",fn.tell()
print fn.read(2)
print "Now at ",fn.tell()
fn.seek(-3, 2)
print "Now at ",fn.tell()
print fn.read(2)
print "Now at ",fn.tell()
fn.close()

程序执行结果如下:

Now at  0
12
Now at  2
Now at  3
45
Now at  5
Now at  2
34
Now at  4
Now at  8
90
Now at  10

21.4 写文件

Python里可以将数据写入文件,要求文件以"w"写的方式打开。如果文件不存在在关闭文件时创建文件。

write函数实现写入

#coding:utf-8
filename = "b.txt"
fw = open(filename, "w")
fw.write("hello\nworld\n")
fw.close()

writelines可将字符串序列写入文件

与readlines函数相对应的writelines函数可以将字符串序列(例如列表)写入文件。

#coding:utf-8
filename = "c.txt"
fw = open(filename, "w")
s = "hello world".split()
s = [x + "\n" for x in s]
fw.writelines(s)
fw.close()

21.5 csv文件读写

Python自带csv模块可以直接读写csv类型的文件。

读csv文件

csv模块里的reader函数reader函数 可以读csv文件里的内容,返回值是可迭代的一种类型。

#coding:utf-8
import csv
filename = "iris.csv"
fn = open(filename, "r")
ret = csv.reader(fn, delimiter=',')
print ret
for x in ret:
    print x
fn.close()

需要说明一点的是reader函数里的形参delimiter=','的意csv文件里的每行数据的每个字段是以逗号间隔的。

数据写入csv

csv提供了writerow、writerows等函数可以将数据写入到csv文件里。 实例:读iris.csv文件,将数据里的逗号换成分号写入iris.txt文件里。

#coding:utf-8
import csv
filenamer = "iris.csv"
fr = open(filenamer, "r")
s = csv.reader(fr, delimiter=',')
filenamew = "iris.txt"
fw = open(filenamew, "w")
ret = csv.writer(fw, delimiter=':')
ret.writerows(s)
fr.close()
fw.close()

下面截图是iris.csv文件。

程序执行完毕后生成的iris.txt文件,截图如下所示。