内置open()函数中,模式a、a+、w、w+和r+之间有什么区别?

847
在Python内置的open函数中,waw+a+r+模式之间的确切区别是什么?
特别地,文档暗示所有这些模式都允许写入文件,并且指出它们分别打开了文件以进行“追加”、“写入”和“更新”,但没有定义这些术语的含义。

13
你提供的链接准确地定义了这些价值观。你对提供的链接哪一部分看不懂或理解不了?请问你能否澄清你的问题,以解释你对链接中没有理解的部分? - S.Lott
@ChrisB. - 我在http://bugs.python.org/issue19627上报告了这个错误。 - Bulwersator
9
有没有一个简单明了的文档可以解释加号的含义? - Charlie Parker
9个回答

974

打开模式与C标准库函数fopen()的一样。

BSD fopen页面将其定义为:

 The argument mode points to a string beginning with one of the following
 sequences (Additional characters may follow these sequences.):

 ``r''   Open text file for reading.  The stream is positioned at the
         beginning of the file.

 ``r+''  Open for reading and writing.  The stream is positioned at the
         beginning of the file.

 ``w''   Truncate file to zero length or create text file for writing.
         The stream is positioned at the beginning of the file.

 ``w+''  Open for reading and writing.  The file is created if it does not
         exist, otherwise it is truncated.  The stream is positioned at
         the beginning of the file.

 ``a''   Open for writing.  The file is created if it does not exist.  The
         stream is positioned at the end of the file.  Subsequent writes
         to the file will always end up at the then current end of file,
         irrespective of any intervening fseek(3) or similar.

 ``a+''  Open for reading and writing.  The file is created if it does not
         exist.  The stream is positioned at the end of the file.  Subse-
         quent writes to the file will always end up at the then current
         end of file, irrespective of any intervening fseek(3) or similar.

29
注意:Python v3 添加了许多额外的模式。链接到文档 - Alex
10
注意:ww+都可以做到“如果文件不存在,则创建文件”的功能。 - Wei Yang
6
在Windows上,添加b到打开文件的模式中会使文件以二进制模式打开,因此还有rbwbr+b等模式。Python在Windows上区分文本文件和二进制文件;当读取或写入数据时,文本文件中的行尾字符会自动稍作修改。 - user4458796
10
我说“+”符号不管是在a,w还是r模式下都没有一个一致的独立作用,这样说对吗?或者我是没看到规律?那么这个规律是什么? - Charlie Parker
3
@CharlieParker:我认为这种模式是“同时也做另一件事”。因此,r+不仅打开文件以供读取,还可以进行写入,而w+则反过来,不仅打开文件以供写入,还可以进行读取。对于a+同样如此。 - balu
显示剩余9条评论

808

我注意到有时候需要再次谷歌 fopen,只是为了建立不同模式之间主要区别的心理图像。因此,我认为下次阅读起来更快的方法是使用一个图表。也许其他人会发现这很有帮助。


4
所以,+ 基本上表示写入。奇怪的是 w 并不意味着这个,而是意味着截断。(阅读下一个答案后,似乎 w 表示覆盖写入,而 a 则表示追加写入,这更有意义…)如果文件不存在,你对创建文件有什么评论吗? - Charlie Parker
6
a的描述是错误的。写入总是定位在末尾。 - Antti Haapala -- Слава Україні
16
我相信@Antti所指的是属性Subsequent writes to the file will always end up at the then current end of file, irrespective of any intervening fseek(3) or similar,这比仅仅说初始位置在末尾要强一些。 - jcai
18
基本上有两种文件操作(读,写)。 r 模式主要用于读取, w_,_a 模式主要用于写入。而 加号会启用给定模式的第二个操作(简单地说)。 - Jeyekomon
72
为了后人:truncate 意味着从开头开始覆盖重写。 - Minh Tran
显示剩余4条评论

293

相同的信息,只是以表格形式呈现

                  | r   r+   w   w+   a   a+
------------------|--------------------------
read              | +   +        +        +
write             |     +    +   +    +   +
write after seek  |     +    +   +
create            |          +   +    +   +
truncate          |          +   +
position at start | +   +    +   +
position at end   |                   +   +

定义如下:

  • read - 允许从文件中读取内容

  • write - 允许向文件中写入内容

  • create - 若文件不存在,则创建该文件

  • truncate - 打开文件时清空文件(即擦除文件中的所有内容)

  • position at start - 文件打开后,初始位置设置为文件开头

  • position at end - 文件打开后,初始位置设置为文件结尾

注意:aa+ 总是将内容追加到文件末尾,忽略任何 seek 操作。
另外,在我的 win7 / python2.7 上以 a+ 模式打开新文件时有趣的行为如下:
write('aa'); seek(0, 0); read(1); write('b') —— 第二个 write 被忽略
write('aa'); seek(0, 0); read(2); write('b') —— 第二个 write 抛出 IOError


16
为什么没有“如果文件不存在,则创建文件。如果存在,则定位于开头,启用读取和写入”?这是我最明显的使用案例:我正在将数据存储在文件中。如果文件不存在,则创建它而不是报错。如果文件中有数据,则我想从顶部读取所有数据,更新一些内容,然后为下次加载完全重新编写文件。我使用open(file,'a');close();open(file,'r +')来完成此操作。 - pinhead
1
@pinhead,您所描述的情况更适合以读模式打开文件,将内容加载到内存中并关闭它,然后在完成时以写模式重新打开它以进行写出。我假设从您所描述的用例中可以看出,您想要整个文件都在内存中,这样即使程序在保存和退出之前终止,也不会损坏文件。 - krs013
2
在这个上下文中,“截断”是什么意思? - Charlie Parker
3
它的意思是文件中的所有内容被清除(文件变为空)。 - industryworker3595112
2
更新表格,以包括Python 3的“x”怎么样? - Nikos Alexandris
显示剩余6条评论

44

这里的选项与C标准库中的fopen函数相同:

w 截断文件,覆盖已存在的内容。

a 追加到文件,添加到已存在的内容之后。

w+ 读写打开文件,截断文件并允许您读取已写入文件的内容。

a+ 追加和读取打开文件,允许您追加到文件并读取其内容。


7
在这个背景下,“truncating”是什么意思? 它是否意味着如果有旧数据,则删除它?还是指其他更具体的内容? 在此上下文中,“truncating”指的是删除或截断旧数据,以便只保留特定长度或数量的数据。 - Charlie Parker
6
@CharlieParker:正确——这意味着现有文件中的所有数据都将被删除,我们将从一个现在为空的文件开始写入。 - Eli Courtwright

31
r r+ x x+ w w+ a a+
可读
可写
默认位置:开头
默认位置:结尾
必须存在
不能存在
加载时截断(清空文件)
始终写入 EOF

模式

t(默认) b
strio.TextIOBase
bytesio.BufferedIOBase

如果未选择模式,则使用文本模式(t)。 因此,rrt相同。


1
“Always write to EOF” 是什么意思? - qff
2
@qff EOF 代表文件结束符。"always" 意味着即使你使用 seek(0)(将光标移动到文件开头),当你使用 write("foo") 时,文件也会写入到文件末尾。这就是为什么它被称为 "append" 模式。你总是将内容追加到文件的末尾。 - Peilonrayz

11

我在试图弄清楚为什么要使用'mode'w+'而不是'w'的情况下,偶然发现了这个。最终,我进行了一些测试。我认为'mode'w+'没有太多用处,因为在两种情况下,文件都会被截断。但是,在使用'w+'的情况下,您可以通过寻找回读写内容。如果您尝试使用'w'进行任何读取,它将引发IOError。使用'mode'w+'时,如果不使用seek进行读取,将无法获得任何结果,因为文件指针将位于您写入的位置之后。


11
我认为这对于跨平台执行非常重要,即作为CYA考虑。 :)
在Windows上,附加到模式的“b”以二进制模式打开文件,因此还有像“rb”,“wb”和“r + b”这样的模式。Python在Windows上区分文本文件和二进制文件;读取或写入数据时,文本文件中的行尾字符会自动略微更改。对于ASCII文本文件,文件数据的这种幕后修改是可以接受的,但是它将破坏像JPEG或EXE文件中那样的二进制数据。读取和写入此类文件时一定要特别小心使用二进制模式。在Unix上,追加“b”到模式不会有影响,因此您可以在所有二进制文件上平台无关地使用它。
这是直接从Python Software Foundation 2.7.x引用的。

9

我认为需要注意的是,Python 3对于打开模式的定义不同于这里正确的Python 2。

Python 3中的打开模式有:

'r' open for reading (default)
'w' open for writing, truncating the file first
'x' open for exclusive creation, failing if the file already exists
'a' open for writing, appending to the end of the file if it exists
----
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newlines mode (for backwards compatibility; should not be used in new code)

模式rwxa与模式修饰符bt结合使用。可选择添加+,应避免使用U

正如我通过艰难的方式发现的那样,总是在文本模式下打开文件时指定t是一个好主意,因为在标准的open()函数中,rrt的别名,但在所有压缩模块的open()函数中(例如读取*.bz2文件时),rrb的别名。

因此,打开文件的模式应为:

rt/wt/xt/at用于以文本模式读取/写入/创建/附加到文件和

rb/wb/xb/ab用于以二进制模式读取/写入/创建/附加到文件。

像以前一样使用+


0
许多人会特别疑惑:“r+和w+模式有什么区别?”
r+帮助你读取和写入数据到已经存在的文件中而不截断(如果没有这样的文件,则出现错误)。
另一方面,w+模式也允许读写但是它会截断文件(如果不存在这样的文件则创建一个新文件)。如果你正在想如何从一个被截断的文件中读取,那么可以使用读取方法来读取新写入的文件(或空文件)。
祝好!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接