文件和流——它们的对象和函数可以让你在程序调用时存储数据,并且可以处理来自其他程序的数据。
打开文件
open
函数使用一个文件名作为唯一的强制参数,然后返回一个文件对象。模式(mode)和缓存(buffering)参数都是可选的。
文件模式
如果open函数只带一个文件名参数,那么我们可以获得能读取文件内容的文件对象。如果要向文件内写入内容,则必须提供一个模式参数来显示声明。
+
参数可以用到其他任何模式中,指明读和写都是允许的。比如r+
能在打开一个文本文件用来读写时使用。
值 | 描述 |
---|---|
'r' | 读模式 |
'w' | 写模式 |
'a' | 追加模式 |
'b' | 二进制模式(可添加到其他模式中使用) |
'+' | 读/写模式(可添加到其他模式中使用) |
b
模式改变处理文件的方法。一般来说,Python假定处理的是文本文件(包含字符)。通常这样做是不会有任何问题的。但如果处理的是一些其他类型的文件(二进制文件),比如声音剪辑或者图像,那么应该在模式参数中增加b
。参数rb
可以用来读取一个二进制文件。
缓冲
open
函数第三个参数(可选)控制着文件的缓冲。如果参数是0(或者是False),I/O(输入/输出)就是无缓冲的(所有读写操作都直接针对硬盘);如果是1(或者是True),I/O就是有缓冲的(意味着Python使用内存来代替硬盘),让程序更快,只有使用了flush或者close时才会更新硬盘上的数据。大于1的数字意味着缓存区的大小(单位是字节),-1(或者时任何负数)表示使用默认的缓冲区大小。
基本的文件方法
类文件对象是支持一些file类方法的对象,最重要的是支持read方法或者write方法,或者两者兼有。urllib.urlopen返回的对象是一个类文件对象。它们支持read、readline和readlines。
读和写
文件(或流)最重要的能力是提供或者接收数据。如果有一个名为f的类文件对象,那么就可以用f.write方法和f.read方法(以字符串形式)写入和读取数据。
每次调用f.write(string)时,所提供的参数string会被追加到文件中已存在部分的后面。
>>> f = open('somefile.txt', 'w')
>>> f.write('Hello, ')
>>> f.write('World!')
>>> f.close()
在完成了对一个文件的操作时,调用close。
读取很简单,只需要记得告诉流要读多少字符(字节)即可。
>>> f = open('somefile.txt', 'r')
>>> f.read(4)
'Hell '
>>> f.read()
'o. World!'
管式输出
管道符号将一个命令的标准输出和下一个命令的标准输入连在一起。
$ cat somefile.txt | python somescript.py | sort
- cat somefile.txt:把somefile.txt的内容写到标准输出(sys.stdout)
- python somescript.py:运行了Python脚本somescript.py。脚本应该是从标准输入读,把结果写到标准输出。
- sort:这条命令从标准输入(sys.stdin)读取了所有的文本,按字母排序,然后把结果写入标准输出。
这样,就知道somescript.py会从它的sys.stdin中读取数据(cat somefile.txt写入的),并把结果写入它的sys.stdout(sort在此得到数据)中。
# somescript.py
import sys
text = sys.stdin.read()
words = text.split()
wordcount = len(words)
print 'Wordcount:', wordcount
Your mother was a hamster and your
father smelled of elderberries.
Wordcount:11
读写行
file.readline方法读取单独的一行。
flie.readlines方法可以读取一个文件中的所有行并将其作为列表返回。
writelines方法和readlines相反:传给他一个字符串的列表,它会把所有的字符串写入文件(或流)。注意,程序不会增加新行,需要自己添加。没有writeline只有wirte
关闭文件
关闭文件可以避免在某些操作系统或设置中进行无用的修改,这样做也会避免用完系统中所打开文件的配额。
写入过的文件总是应该关闭的,是因为Python可能会缓存(出于效率考虑, 可能会把文件临时的储存在某地)写入的数据,如果程序因为某些原因崩溃了,那么数据根本不会被写入文件。为了安全起见,要在使用完文件后关闭。
使用with语句可以解决这种关闭文件问题
with open('somefile.txt') as somefile:
do_something(fomefile)
with语句可以打开文件并且将其赋值到变量上(本例是somefile)。之后就可以将数据写入语句体中的文件(或执行其他操作)。文件在语句结束后会被自动关闭,即使是由于异常引起的结束也是如此。
使用基本文件方法
一个简单的文本文件
Welcome to this file
There is nothing here except
This stupid haiku
>>> f = open(r'c:\text\somefile.txt')
>>> f.read(7)
'to'
>>> f.close()
>>> f = open(r'c:\text\somefile.txt')
>>> print f.read()
Welcome to this file
There is nothing here except
This stupid haiku
>>> f.close()
>>> f = open(r'c:\text\somefile.txt')
>>> for i in range(3):
print str(i) + ':' + f.readline()
0:Welcome to this file
1:There is nothing here except
2:This stupid haiku
>>> f.close()
>>> import pprint
>>> pprint.pprint(open(r'c:\text\somefile.txt').readlines())
['Welcome to this file\n',
'There is nothing here except\n',
'This stupid haiku']
>>> f = open(r'c:\text\somefile.txt')
>>> f.write('this\nis no\nhaiku')
>>> f.close()
>>> f = open(r'c:\text\somefile.txt')
>>> lines = f.readlines()
>>> f.close()
>>> lines[1] = "isn't a\n"
>>> f = open(r'C:\text\somefile.text', 'w')
>>> f.writelines(lines)
>>> f.close()
对文件内容进行迭代
按字节处理
在while循环中使用read方法。
f = open(filename)
while True:
line = f.readline()
if not line: break
process(line)
按行操作
f = open(filename)
while True:
line = f.readline()
if not line: break
process(line)
f.close()
读取所有内容
如果文件不是很大,可以使用不带参数的read方法一次读取整个文件(把整个文件当做一个字符串来读取),或者使用readlines方法(把文件读入一个字符串列表,在列表中每个字符串就是一行)
使用fileinput实现懒惰行迭代
在需要对一个非常大的文件进行行迭代的操作时,readlines会占用太多的内存。这儿时候可以使用while循环和readline方法替代。
import fileinput
for line in fileinput.input(filename):
process(line)
文件迭代器
文件对象是可迭代的,这就意味着可以直接在for循环中使用它们,从而对它们进行迭代。
f = open(filename)
for line in f:
process(line)
只要没有向文件内写入内容,那么不关闭文件也是可以的。
···
for line in open(filename):
process(line)
···
小结
类文件对象
打开和关闭文件
模式和文件类型
标准流
读和写
读写行
迭代文件内容