【问题标题】:Confused by python file mode "w+"被python文件模式“w+”弄糊涂了
【发布时间】:2013-04-18 23:04:18
【问题描述】:

来自doc

模式“r+”、“w+”和“a+”打开文件进行更新(注意“w+”会截断文件)。在区分二进制文件和文本文件的系统上,将“b”附加到模式以二进制模式打开文件;在没有这种区别的系统上,添加“b”无效。

here

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

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

【问题讨论】:

  • 我发现this 图表很有用。

标签: python file io


【解决方案1】:

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

  • r

    以只读方式打开文件。文件指针位于文件的开头。这是默认模式。

  • rb

    以二进制格式打开一个只读文件。文件指针位于文件的开头。这是默认模式。

  • r+

    打开一个文件进行读写。文件指针将位于文件的开头。

  • rb+

    以二进制格式打开一个文件进行读写。文件指针将位于文件的开头。

  • w

    打开一个文件仅用于写入。如果文件存在,则覆盖文件。如果文件不存在,则创建一个新文件进行写入。

  • wb

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

  • w+

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

  • wb+

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

  • 一个

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

  • ab

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

  • 一个+

    打开一个文件以进行追加和读取。如果文件存在,则文件指针位于文件末尾。该文件以附加模式打开。如果文件不存在,则创建一个新文件进行读写。

  • ab+

    以二进制格式打开一个文件以进行追加和读取。如果文件存在,则文件指针位于文件末尾。该文件以附加模式打开。如果文件不存在,则创建一个新文件进行读写。

【讨论】:

  • @Humdinger: 不,w+ 创建一个新文件或截断现有文件,然后打开它进行读写; r+ 打开现有文件而不截断它以进行读写。非常不同。
  • 另外,就像@AlokAgarwal 的回答一样,这声称是一个详尽的模式列表,但不是。
  • 给出一个详尽的模式列表是相当愚蠢的,因为它们的功能更像是一个具有多个参数的函数。 rwa 是排他性的,但 b 可以添加到其中任何一个,+U 也可以......这是一个组合爆炸。
  • rb 不是默认模式,引用:The most commonly-used values of mode are 'r' for reading, 'w' for writing (truncating the file if it already exists), and 'a' for appending (which on some Unix systems means that all writes append to the end of the file regardless of the current seek position). If mode is omitted, it defaults to 'r'docs.python.org/2/library/functions.html#open
  • 也许我们可以添加“x”模式,也就是“独占创建”:如果文件不存在则创建文件(用于写入),如果不存在则引发 FileExistsError。
【解决方案2】:

Python 中的所有文件模式

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

【讨论】:

  • 这不是所有的模式。它忽略了,例如 rbwb,更不用说 2.x 中的 U 模式和 3.x 中的 t 模式(它们都可以与除 b 之外的所有内容组合)。
  • r+ 和 w+ 的区别在于 w+ 在打开文件时会截断文件。但是您可以在两种模式下手动截断它。
  • 这个答案与@200 OK 给出的答案不一致,例如wb+ 是否也从文件中读取?
  • @Celeritas wb 表示打开文件以二进制模式写入。在 Unix 系统(Linux、Mac OS X 等)上,二进制模式什么都不做——它们处理文本文件的方式与处理任何其他文件的方式相同。但是,在 Windows 上,文本文件的行尾略有修改。在处理实际的二进制文件(如 exe 或 jpg 文件)时,这会导致严重的问题。因此,当打开不应该是文本的文件时,即使在 Unix 中,也应该使用 wb 或 rb。仅对文本文件使用纯 w 或 r。
  • 在 Python 3 中,还有 'x' 的打开模式:打开用于独占创建,如果文件已经存在则失败。请参阅文档中的open 函数。
【解决方案3】:

假设您正在使用 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() 调用将尝试从文件末尾读取,并返回一个空字符串。

【讨论】:

  • “截断为 0 字节”是什么意思?
  • @NasifImtiazOhi - Python 文档说w+ 将“如果文件存在则覆盖现有文件”。因此,只要您使用w+ 打开一个文件,它现在就是一个空文件:它包含 0 个字节。如果它曾经包含数据,则该数据已被截断(截断并丢弃),现在文件大小为 0 字节,因此您无法读取 在打开之前存在的任何数据带有w+ 的文件。如果你真的想读取之前的数据并添加,你应该使用r+而不是w+
  • 如何在顶部添加新数据?
  • @BeqaBukhradze - 如果您有任何问题,请单击“提问”按钮,数百人将在此处看到。不要只点击“添加评论”按钮,只有一两个人会看到它。
  • @BeqaBukhadraze 使用“a”模式
【解决方案4】:

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
$

【讨论】:

    【解决方案5】:

    两者似乎工作相同,但有一个问题。

    r+ :-

    • 打开文件进行读写
    • 一旦在开始文件中打开,指针将指向 0
    • 现在,如果您想阅读,那么它将从头开始阅读
    • 如果你想写那么就开始写,但是写过程将从指针0开始。所以会有字符覆盖,如果有的话
    • 在这种情况下 File 应该存在,要么会引发 FileNotFoundError

    w+ :-

    • 打开文件进行读写
    • 如果文件存在,将打开文件并清除所有数据,
    • 如果文件不存在,则创建新文件
    • 在开始的文件指针将指向 0(因为没有数据)
    • 现在如果你想写点什么,那就写吧
    • 文件指针现在将指向文件结尾(在写入过程之后)
    • 如果您现在想读取数据,请寻找特定点。 (用于开始寻找(0))

    所以,总的来说,两者都是为了打开文件进行读写,但区别在于我们是要在开始时擦除数据然后进行读/写还是直接开始。

    abc.txt - 开头

    1234567
    abcdefg
    0987654
    1234
    

    Code for 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
    

    Output

    0
    567
    abcdefg
    0987654
    1234
    

    abc.txt - 运行后:

    abcd567
    abcdefg
    0987654
    1234Sunny
    

    将 abc.txt 重置为初始值

    Code for 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
    

    Output

    0
    
    
    

    abc.txt - 运行后:

    abcdSunny
    

    【讨论】:

      【解决方案6】:

      文件被截断,因此您可以调用read()(不会引发异常,与使用'w'打开时不同)但您会得到一个空字符串。

      【讨论】:

        【解决方案7】:

        我怀疑有两种方法可以处理我认为您想要实现的目标。

        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+
        【解决方案8】:

        实际上,关于r+ 模式的所有其他答案都有问题。

        test.in文件内容:

        hello1
        ok2
        byebye3
        

        还有 py 脚本的:

        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) 开始覆盖它们。

        【讨论】:

          【解决方案9】:

          这里的列表可能会有所帮助

          字符 含义

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

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

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

          'a' - 打开写入,如果存在则追加到文件末尾

          'b' - 二进制模式

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

          '+' - 打开更新(读写)

          默认模式是'r'(打开阅读文本,'rt'的同义词)。模式“w+”和“w+b”打开并截断文件。 'r+' 和 'r+b' 模式打开文件时不会截断。

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

          【讨论】:

            【解决方案10】:

            我也很困惑……但我的回答可能会对某人有所帮助。 我假设您想利用 'w+' 模式的功能来创建文件(如果文件不存在)。

            确实,如果文件不存在,只有 w, w+, a, a+ 可以创建。

            但是,如果您需要读取文件的数据(包含数据的文件确实存在的情况),您无法使用 w+ 开箱即用,因为它会截断文件。糟糕,你不是那个意思!

            所以,你最好的朋友可能是 file.seek(0) 的 a+:

            with open('somefile.txt', 'a+') as f:
                f.seek(0)
                for line in f:
                    print(f.readline())
            

            【讨论】:

              【解决方案11】:

              正如h4z3 所提到的, 为了实际使用, 有时您的数据太大而无法直接加载所有内容,或者您​​有生成器,或者实时传入数据,您可以使用 w+ 存储在文件中并稍后读取。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2022-01-23
                • 2019-01-12
                • 1970-01-01
                • 1970-01-01
                • 2014-08-14
                • 2016-02-16
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多