python open()函数打开文件的模式详解
使用python处理文件时,避免不了要用到open()函数。我们今天主要讨论mode参数的区分。
fd = open('文件名(路径)’, mode=‘模式’)
先放上stockoverflow上一个哥么做的图,很清楚的从总体上概括了mode的区分;
图中展示了几种主要的模式,r(只读),r+(读写),w(只写), w+(读写), a(追加),a+(追加读)
从功能上分类:模式r只有读的功能,模式w和a只有写的功能,模式r+,w+和a+拥有读和写的功能。
读的功能就是,文件读入的对象可以使用read读取文件内容,不用使用write方法向写入内容;写的功能是反过来的,
可以使用write方法向写入内容,不用使用read读取文件内容,而读写就是这两个功能都有。
说到这里模式之间的区别还是不清楚。我们可以接着看下面这张图来进一步认识模式间的区别:
------------------|r r+w w+a a+read | + + + +write | + + + + +write after seek | + + +create | + + + +truncate | + +position at start |+ + + +position at end | + +
1,r和r+的区别
先试着执行下面代码:
1 fd1 = open('newfile1.txt', mode='r')
2 fd2 = open('newfile2.txt', mode='r+')
如果你的工作目录下没有newfile.txt的话,运行这两行代码会出现FileNotFoundError报错信息,告诉
你“本路径下没有名叫newfile.txt的这个文件”,可以先创建一个名为newfile.txt的文件再执行上面代码就不会出问题了,
接着执行:
1 fd1.read()
2 fd2.read()
代码正常执行,返回空字符串;返回空字符串是因为你的文件里什么原本就什么就没有
接着执行:
1 fd1.write('this is test')
2 fd2.write('this is test')
第一行代码报错io.UnsupportedOperation: not writable,第二行代码正常运行,这里就是r和r+的区别了
r只有读的功能,r+既有读的功能,也有写的功能。
2,w和w+的区别
1 fd1 = open('newfile1.txt', mode='w')
2 fd2 = open('newfile2.txt', mode='w+')
3 fd1.write('this is test')
4 fd2.write('this is test')
5 fd1.read()
6 fd2.read()
与r和r+不同的是,无论当前目录下有没有名字为newfile.txt的文件,第一第二行都会正常运行,如果没有的话会在当前目录下创建一个名为newfile.txt的文件。
第三第四行也会正常运行,并将字符串写入文件,
第五行会报错:io.UnsupportedOperation: not readable,第六行会正常运行;这说明w和w+的区别是后者兼有读写功能,前这只有写的功能。
第六行虽然运行成功了,但是返回的确是空字符串,问题是我们在读取之前已经写入了内容呀?这
是因为写入结束之后我们的指针放在文件的末尾,这时候你读取的就是末尾之后的东西,也就是空
字符串了。可以尝试一下方法解决:
(1)先关闭文件再打开文件读取
1 fd2.close()
2 fd2 = open('newfile2.txt', mode='r')
3 fd2.read()
这样的话会正常显示我们之前写入的内容,这个方法未免太“折腾”了
(2)移动指针到文件开头再读取
1 fd2.seek(0)
2 fd2.read()
这样也可以成功读取刚写入的内容,seek(0)中的0表示offset=0,偏移0个字符,还有一个参数whence默认为0代表从文件开始位置,另外还有1代表当前位置,2代表文件末尾。
3,a和a+的区别:
模式a和a+之间的区别与w和w+之间的区别相同,在此不做赘述
4,a和w的区别
模式a和w都是写,区别就在于从哪里开始写,为了说明问题,我们先新创建两个文件new1.txt和new2.txt内容都为:
this is test1
this is test2
this is test3
然后执行下面代码:
1 fd1 = open('new1.txt', mode='w')
2 fd1.write('try to update')
3 fd1.seek(0)
4 fd1.read()
输出的结果为:
try to update
new1.txt文件中的原始内容被“冲洗”掉了!,我们再试试追加模式a
1 fd2 = open('new2.txt', mode='a')
2 fd2.write('try to update')
3 fd2.seek(0)
4 fd2.read()
返回的结果为:
this is test1
this is test2
this is test3
try to update
在文本的末尾添加了新写入的内容。上面就是模式w和a的区别,w在打开文件的
时候将指针移动到文件开头并截断(truncate)了之后的所有内容,截断即删除掉了。
而模式a开打文件的时候,其指针的位置是在文件的末尾。所以写入新内容的时候
这两种模式就会不一样。
值得一提的是,以模式a打开一个当前目录下不存在的文件也同样会新创建该文件。
5,r+和w+之间的比较
r+和w+之间是有必要拿出来比较一下的,因为他们的功能还是很像的,先说相同点
(1)都是可读可写的
(2)打开文件时指针都位于开始位置
再说不同点,创建两个新文件new3.txt和new4.txt内容都为:
this is one
this is two
this is three
尝试以下代码:
1 fd3 = open('new3.txt', mode='r+')
2 fd3.write('1234')
3 fd3.seek(0)
4 fd3.read()
返回的结果是:
1234 is one
this is two
this is three
仅仅是替换了new3.txt原来位置的字符,其他未变!我们再试试w+
1 fd4 = open('new4.txt', mode='w+')
2 fd4.write('1234')
3 fd4.seek(0)
4 fd4.read()
返回的结果为:
1234
结果一目了然了。
关于with open:
使用Python内置的open()函数打开文件,如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在:
>>> f=open('/Users/michael/notfound.txt', 'r')
Traceback (most recent call last):
File "", line 1, in
FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/notfound.txt'
如果文件打开成功,则可以根据文件对象对文本内容进行操作,如调用read()方法可以一次读取文件的全部内容:
>>> f.read()
'Hello, world!'
最后一步是调用close()方法关闭文件,用来释放文件对象占用操作系统的资源
>>> f.close()
由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现:
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:
with open('/Users/michael/notfound.txt', 'r') as f:
print(f.read())
这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
另,with open() as f的方式可以同时管理多个文件对象,如下:
with open('/Users/michael/notfound1.txt', 'r') as fr,open('/Users/michael/notfound2.txt', 'w') as fw,:
for line in fr.readlines():
fw.write(line)
读取超大文件时,如几十G文件,为了避免一次读取全部内容,可以使用with open()获取文件句柄进行逐行读取,每次内存中只保存一行数据:
with open("test.txt") as f:for line inf:#do something with data