IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。
通常程序完成IO操作会有Input和Output两个数据流:
访问网页时浏览器首先会向外发送数据给所访问网页的服务器,获取该网页首页的HTML,该过程即为输出Output;随后网页服务器将网页发过来,该过程是从外面接收数据,叫输入Input。
从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作。
IO编程中,Stream(流)是一个很重要的概念,把流想象成一个水管,数据就是水管里的水,但是只能单向流动。
对于浏览网页来说,浏览器和新浪服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。
- IO编程中,存在速度严重不匹配:CPU和内存的速度>>>>外设的速度
如:把100M的数据写入磁盘,TCPU输出100M数据 = 0.01s,T磁盘接收100M数据 = 10s
解决办法:①同步IO:CPU等着,即程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行。【逛商场前买奶茶需5min,选择柜台前干等5min】
②异步IO:一边是CPU立刻接着执行后续代码,一边是磁盘慢慢写入数据。【逛商场前买奶茶需5min,你选择先去逛一逛】
同步和异步的区别就在于是否等待IO执行的结果。
使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。
操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。
File对象的属性
一个文件被打开后,你有一个file对象,你可以得到有关该文件的各种信息。
以下是和file对象相关的所有属性的列表:
属性 | 描述 |
file.closed | 返回true如果文件已被关闭,否则返回false。 |
file.mode | 返回被打开文件的访问模式。 |
file.name | 返回文件的名称。 |
file.softspace | 如果用print输出后,必须跟一个空格符,则返回false。否则返回true。 |
# 打开一个文件
fo = open("foo.txt", "w")
print "文件名: ", fo.name
print "是否已关闭 : ", fo.closed
print "访问模式 : ", fo.mode
print "末尾是否强制加空格 : ", fo.softspace
以上实例输出结果:
文件名: foo.txt
是否已关闭 : False
访问模式 : w
末尾是否强制加空格 : 0
文件读写
文件:存储在外部介质(如:磁盘)上的数据或信息的集合
文本文件:一般指只要字符编码存储的文件,能够被最简单的文本编辑器直接读取
在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
- 文件的操作步骤:打开文件 → 操作文件(读、写等)→ 关闭文件。
①打开文件:file object = open(file_name [, access_mode [,encoding = None [, errors = None] ] ])
file_name:文件名(包括路径);
access_mode:access_mode决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
encoding = None 默认读取UTF-8编码的文件。如果要读取非UTF-8编码的文本文件,就需要传入encoding
参数。
errors = None errors的取值一般有strict,ignore,当取strict的时候,字符编码出现问题的时候,会报错,当取ignore的时候,编码出现问题,程序会忽略而过,继续执行下面的程序。
打开模式 | 含义 |
r(默认) | 只读方式打开。文件的指针将会放在文件的开头,文件不存在则报错IOError 。 |
w | 只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。即,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片、视频等。 |
#读取GBK编码的文件
>>> f = open('/Users/Tony/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'
如果文件不存在,open()函数就会抛出一个IOError
的错误。
②操作文件——读read()& readline() & readlines()
fileObject.read(size) 返回从字符串中读取的字节,如果未给定size或给负值则读取所有。
#假设有一个python.txt文件,文件内容为:i love python!
# 打开一个文件,用于读写
fo = open("python.txt", "r+")
#读取python.txt文件里的前10个字符
str = fo.read(10)
print "读取的字符串是 : ", str
# 关闭打开的文件
fo.close()
以上实例输出的结果为:i love pyt
调用read()
会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)
方法,每次最多读取size个字节的内容。另外,调用readline()
可以每次读取一行内容,调用readlines()
一次读取所有内容并按行返回list
。因此,要根据需要决定怎么调用。
如果文件很小,read()
一次性读取最方便;如果不能确定文件大小,反复调用read(size)
比较保险;如果是配置文件,调用readlines()
最方便。
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
str.strip(chars) 用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
【chars——需移除的位于首尾的字符系列】
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
②操作文件——写write()& writelines()
fileObject.write(str) 用于向文件中写入指定字符串,Python字符串可以是二进制数据,而不是仅仅是文字。
如果文件打开模式带 b,那写入文件内容时,str (参数)要用 encode 方法转为 bytes 形式,否则报错:TypeError: a bytes-like object is required, not 'str'。
fileObject.write(str) 用于向文件中写入字符串列表。可以是由迭代对象产生的。换行需要制定换行符 \n。
#write( ) str
>>> f=open(r'D:\python36\projects\text.txt','w') #这里说明该文件是用来写入的
>>> words="争分夺秒\n" #自己添加'\n'
>>> f.write(words) #write(str)的参数是str
5 #返回写入字符的个数
>>> f.close() #写入文件后f.close(),文件才真正写入上面字符
>>> open(r'D:\python36\projects\text.txt','r').read()
'争分夺秒\n'
>>> print(open(r'D:\python36\projects\text.txt','r').read())
争分夺秒 #该文件内只有一个词争分夺秒。
#writelines( ) list
>>> f=open(r'D:\python36\projects\text.txt','w') #这里说明该文件是用来写入的
>>> words=["争分夺秒\n","力争上游\n"] #自己添加'\n'
>>> f.writelines(words) #writelines([list])无返回值
>>> f.close() #写入文件后f.close(),文件才真正写入上面字符
>>> open(r'D:\python36\projects\text.txt','r').read()
'争分夺秒\n,力争上游\n'
>>> print(open(r'D:\python36\projects\text.txt','r').read())
争分夺秒
力争上游
③关闭文件——close()
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。
fileObject.close() 用于关闭一个已打开的文件。
关闭后的文件不能再进行读写操作, 否则会触发 ValueError 错误。 close() 方法允许调用多次。
当 file 对象,被引用到操作另外一个文件时,Python 会自动关闭之前的 file 对象。
- 在Python中,文件读写是通过
open()
函数打开的文件对象完成的。使用with
语句操作文件IO是个好习惯。
由于文件读写时都有可能产生IOError
,一旦出错,后面的f.close()
就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally
来实现或者引入with语句来自动帮我们调用close()
方法。
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
#每次写入try ... finally过于繁琐,可使用with,且不比调用f.close():
with open('/path/to/file', 'r') as f:
print(f.read())