Python文件模式"w+"让您感到困惑了吗?

277

来自文档

'r+'、'w+'和'a+'模式打开文件进行更新(注意,'w+'截断文件)。在区分二进制和文本文件的系统上,在模式后添加'b'以二进制模式打开文件;对于没有此区别的系统,在模式后添加'b'没有任何影响。

还有这里

w+:为写入和读取打开文件。如果文件存在,则覆盖现有文件;如果文件不存在,则创建一个新文件进行读取和写入。

但是,如何读取使用w+打开的文件?


36
我发现这个图示非常有用。 - Ritwik
11个回答

556

以下是打开文件的不同模式列表:

  • r

    只读方式打开文件。文件指针放在文件的开头,这是默认模式。

  • rb

    以二进制格式只读方式打开文件。文件指针放在文件的开头,这是默认模式。

  • r+

    可读写方式打开文件。文件指针将位于文件开头。

  • rb+

    以二进制格式可读写方式打开文件。文件指针将位于文件开头。

  • w

    只写方式打开文件。如果文件存在,则覆盖文件。如果文件不存在,则创建一个新文件进行写入。

  • wb

    以二进制格式只写方式打开文件。如果文件存在,则覆盖文件。如果文件不存在,则创建一个新文件进行写入。

  • w+

    可读写方式打开文件。如果文件存在,则覆盖现有文件。如果文件不存在,则创建一个新文件进行读写。

  • wb+

    以二进制格式可读写方式打开文件。如果文件存在,则覆盖现有文件。如果文件不存在,则创建一个新文件进行读写。

  • a

    打开一个文件进行追加写入。如果文件存在,文件指针位于文件末尾,也就是说文件处于追加模式。如果文件不存在,它会创建一个新的文件进行写入。

    ab

    以二进制格式打开文件进行追加写入。如果文件存在,文件指针位于文件末尾,也就是说文件处于追加模式。如果文件不存在,它会创建一个新的文件进行写入。

    a+

    同时打开一个文件进行追加和读取操作。如果文件存在,文件指针位于文件末尾,文件以追加模式打开。如果文件不存在,它会创建一个新的文件进行读写操作。

    ab+

    同时以二进制格式打开一个文件进行追加和读取操作。如果文件存在,文件指针位于文件末尾,文件以追加模式打开。如果文件不存在,它会创建一个新的文件进行读写操作。


30
@Humdinger:不,w+会创建一个新文件或截断现有文件,然后打开它以供读写;r+打开现有文件以供读写,但不会截断它。两者非常不同。 - abarnert
1
同样地,就像@AlokAgarwal的回答一样,这声称是模式的详尽列表,但实际上并不是。 - abarnert
1
给出模式的详尽列表是相当愚蠢的,因为它们更像是具有多个参数的函数。rwa是互斥的,但b可以添加到其中任何一个,+U也可以添加到其中任何一个……这是一种组合爆炸。 - rmunn
4
rb不是默认模式,引用原文:mode最常用的值是'r'表示读取,'w'表示写入(如果文件已经存在则截断),而'a'表示追加(在某些Unix系统上,所有写入都会追加到文件的末尾,无论当前的寻找位置在哪里)。如果省略了mode参数,则默认为'r'。https://docs.python.org/2/library/functions.html#open - iggy
3
也许我们可以添加“x”模式,即“独占创建”:如果文件不存在,则创建该文件(用于写入),否则引发FileExistsError错误。 - András Aszódi
显示剩余3条评论

172

Python中的所有文件模式

  • r 读取文件
  • r+ 可读可写(不能截断文件)
  • w 写入文件
  • w+ 可读可写(可以截断文件)
  • rb 读取二进制文件。 文件指针放置在文件开头。
  • rb+ 读取或写入二进制文件
  • wb+ 写二进制文件
  • a+ 追加方式打开
  • ab+ 以追加和读取二进制方式打开文件。 如果文件存在,则文件指针位于文件末尾。文件以追加方式打开。
  • x 独占创建,如果文件已存在则失败 (Python 3)

5
这并不是全部模式。例如,它忽略了rbwb,更不用说2.x版本中的U模式和3.x版本中的t模式(这两种模式都可以与除了b以外的所有模式组合使用)。 - abarnert
1
r+和w+之间的区别在于,w+在打开文件时会截断它。但是在两种模式下都可以手动截断它。 - Martin
2
这个答案与@200 OK给出的答案不一致,例如wb+是否也从文件中读取? - Celeritas
@Celeritas wb 表示以二进制模式打开文件进行写入。在 Unix 系统(Linux、Mac OS X 等)上,二进制模式不起作用 - 它们处理文本文件的方式与处理其他文件的方式相同。但是,在 Windows 上,文本文件会使用稍微修改过的行结尾进行写入。这在处理实际的二进制文件(如 exe 或 jpg 文件)时会导致严重问题。因此,即使在 Unix 中,当打开不应为文本的文件时,也应使用 wb 或 rb。仅对于文本文件使用普通的 w 或 r。 - Alok Agarwal
在Python 3中,还有'x'打开模式:用于独占式创建文件,如果文件已经存在,则失败。请参见文档中的open函数。 - Laurent LAPORTE
显示剩余2条评论

168

假设你正在使用with语句打开文件,按照正确的方式。那么你可以像这样从文件中读取:

with open('somefile.txt', 'w+') as f:
    # Note that f has now been truncated to 0 bytes, so you'll only
    # be able to read data that you write after this point
    f.write('somedata\n')
    f.seek(0)  # Important: return to the top of the file before reading, otherwise you'll just read an empty string
    data = f.read() # Returns 'somedata\n'

请注意 f.seek(0) -- 如果你忘记这个步骤,f.read() 会试图从文件的末尾读取数据,并返回一个空字符串。


3
“truncating to 0 bytes” 的意思是将文件或数据截断到空(0)字节的长度。 - Nasif Imtiaz Ohi
31
Python文档中指出,使用w+会“覆盖掉已经存在的文件”。因此,一旦你使用w+打开一个文件时,它就是一个空文件:它不包含任何字节。如果它之前包含有数据,那么这些数据已经被截断、丢弃了,现在文件大小是0字节,所以在使用w+打开文件之前的数据将无法读取。如果你希望读取以前的数据并添加新的数据,你应该使用r+而不是w+ - rmunn
如何在顶部添加新数据? - Beqa Bukhradze
3
@BeqaBukhradze - 如果您有问题,请点击“提问”按钮,这样将会被数百人看到。不要只是点击“添加评论”按钮,那里只有一两个人会看到它。 - rmunn
@BeqaBukhadraze 使用“a”模式。 - Psychzander
@rmunn,你觉得我的回答怎么样?它可以防止意外丢失数据。 - Andrew Anderson

16

r表示读取文件。

w表示写入文件。

r+表示读写文件,如果文件存在,则不会删除原有内容,否则会引发异常。

w+表示覆盖文件内容进行读写,如果文件存在,则会删除原有内容,否则将创建新的文件。

例如:

>>> with open("file1.txt", "w") as f:
...   f.write("ab\n")
... 
>>> with open("file1.txt", "w+") as f:
...   f.write("c")
... 

$ cat file1.txt 
c$
>>> with open("file2.txt", "r+") as f:
...   f.write("ab\n")
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'file2.txt'

>>> with open("file2.txt", "w") as f:
...   f.write("ab\n")
... 
>>> with open("file2.txt", "r+") as f:
...   f.write("c")
... 

$ cat file2.txt 
cb
$

8

它们似乎都是同样有效的,但有一个注意点。

r+ :-

  • 打开文件进行读取和写入
  • 一旦打开,文件指针将指向0
  • 现在,如果你想读取,那么它将从开头开始读取
  • 如果你想写,则开始写入,但写入过程将从指针0开始。所以如果有任何内容,就会覆盖字符。
  • 在这种情况下,文件应该存在,否则将引发 FileNotFoundError

w+ :-

  • 打开文件进行读取和写入
  • 如果文件存在,则打开文件并删除所有数据,
  • 如果文件不存在,则创建新文件
  • 在开始时,文件指针将指向0(因为没有数据)
  • 现在,如果你想写入某些内容,那就写
  • 文件指针现在指向文件末尾(写入过程后)
  • 如果你想读取数据,现在请寻找特定点。(对于起点,使用seek(0))

因此,总体来说,两者都旨在打开文件进行读写,但区别在于是否要在开头擦除数据,然后进行读/写或者直接开始。

abc.txt - 开始时

1234567
abcdefg
0987654
1234

r+ 的代码

with open('abc.txt', 'r+') as f:      # abc.txt should exist before opening
    print(f.tell())                   # Should give ==> 0
    f.write('abcd')                   
    print(f.read())                   # Pointer is pointing to index 3 => 4th position
    f.write('Sunny')                  # After read pointer is at End of file

输出

0
567
abcdefg
0987654
1234

abc.txt - 运行后:

abcd567
abcdefg
0987654
1234Sunny

将 abc.txt 重置为初始状态

w+ 的代码

with open('abc.txt', 'w+') as f:     
    print(f.tell())                   # Should give ==> 0
    f.write('abcd')                   
    print(f.read())                   # Pointer is pointing to index 3 => 4th position
    f.write('Sunny')                  # After read pointer is at End of file

输出

0


abc.txt - 运行后:

abcdSunny

2
实际上,其他关于r+模式的答案都存在问题。 test.in文件的内容:
hello1
ok2
byebye3

而 Python 脚本的:

with open("test.in", 'r+')as f:
    f.readline()
    f.write("addition")

执行此操作后,test.in 的内容将被更改为:
hello1
ok2
byebye3
addition

然而,当我们修改脚本为:
with open("test.in", 'r+')as f:
    f.write("addition")

test.in 也会进行响应:

additionk2
byebye3

所以,r+ 模式将允许我们在没有进行读取操作的情况下从开头覆盖文件内容。如果我们进行了一些读取操作,f.write() 将只是追加到文件中。
顺便说一句,如果在 f.write(write_content) 之前执行 f.seek(0,0),write_content 将从位置 (0,0) 开始覆盖它们。

2
我猜你试图实现的目标有两种方法。
1)显而易见的方法是只读打开文件,将其读入内存,然后使用t打开文件,进行更改。
2)使用低级别的文件处理例程:
# Open file in RW , create if it doesn't exist. *Don't* pass O_TRUNC
 fd = os.open(filename, os.O_RDWR | os.O_CREAT)

希望这可以帮到您。

那么 r+ 是用来做什么的? - Smart Manoj

2
文件被截断了,所以你可以调用read()(不会引发异常,与使用“w”打开时不同),但是你会得到一个空字符串。

1

以下是可能有帮助的列表

字符 含义

'r' - 打开以供阅读(默认)

'w' - 打开以供写入,首先截断文件

'x' - 打开以供独占创建,如果文件已经存在则失败

'a' - 打开以供写入,如果文件存在则将内容附加到文件末尾

'b' - 二进制模式

't' - 文本模式(默认)

'+' - 打开以供更新(读取和写入)

默认模式为“r”(打开文本进行阅读,与“rt”同义)。 模式“w +”和“w + b”打开并截断文件。 模式“r +”和“r + b”打开文件而不截断。

Reference:https://docs.python.org/3/library/functions.html#open


1
我也曾经感到非常困惑......但是我的答案可能会帮助到某些人。我假设您想利用“w+”模式创建不存在的文件的能力。
确实,只有“w”,“w+”,“a”,“a+”可以在文件不存在时进行创建。
但是,如果您需要读取文件的数据(即存在数据的情况),则无法使用“w+”来完成,因为它会截断文件。糟糕,您不是这个意思!
因此,最好的选择可能是使用“a+”以及“file.seek(0)”:
with open('somefile.txt', 'a+') as f:
    f.seek(0)
    for line in f:
        print(f.readline())

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