简体   繁体   English

`r+`, `a+`, `w+` 用于在 python 中读写文件

[英]`r+`, `a+`, `w+` for doing both reading and writing file in python

I have a file named dict_file.json in current folder with empty dict content {}我在当前文件夹中有一个名为dict_file.json的文件,其中 dict 内容为空{}

I want to open it such that I can do both read and modify the content.我想打开它,以便我可以阅读和修改内容。 That is I will read the json file as dict , modify that dict and write it back to json file.也就是说,我将 json 文件读取为dict ,修改该dict并将其写回 json 文件。

I tried r and r+ below:我在下面尝试rr+

import json
f = open('dict_file.json', 'r')  # same output for r+
json.loads(list_file.read())

This prints这打印

{}

When I tried w+ :当我尝试w+时:

f = open('dict_file.json', 'r')

this first clears the file.这首先清除文件。 Then,然后,

json.loads(list_file.read())

gives error:给出错误:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "F:\ProgramFiles\Python37\lib\json\__init__.py", line 296, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "F:\ProgramFiles\Python37\lib\json\__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "F:\ProgramFiles\Python37\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "F:\ProgramFiles\Python37\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

When I tried a+ :当我尝试a+时:

f = open('dict_file.json', 'a+')
json.loads(list_file.read())

gives error:给出错误:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "F:\ProgramFiles\Python37\lib\json\__init__.py", line 296, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "F:\ProgramFiles\Python37\lib\json\__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "F:\ProgramFiles\Python37\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "F:\ProgramFiles\Python37\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Though, it does not clear the file.虽然,它不会清除文件。

So, I guess I should be using r+ for my usecase scenario.所以,我想我应该在我的用例场景中使用r+ Also I tried reading writing both:我也尝试阅读写作:

f = open('dict_file.json', 'r+')
a = json.loads(list_file.read())
a = {'key':'value'}  # this involves complex logic instead of plain assignment
json.dump(a,f)
f.flush()

Now when I open the file, its contents are weird:现在当我打开文件时,它的内容很奇怪:

{}{'key':'value'}

whereas I want it to be:而我希望它是:

{'key':'value'}

So I have few questions:所以我有几个问题:

Q1. Q1。 Why w+ and a+ gives error?为什么w+a+会出错?
Q2. Q2。 Why file contained {}{'key':'value'} instead of {'key':'value'} ?为什么文件包含{}{'key':'value'}而不是{'key':'value'}
Q3. Q3。 How to correctly do reading and writing (with or without with block)?如何正确进行读写(有或没有with块)?

PS: I am reading file, then running some loop which computes new dict and write it to file. PS:我正在读取文件,然后运行一些循环来计算新的字典并将其写入文件。 Then loop sleeps for some time and repeats the same.然后循环休眠一段时间并重复相同的操作。 Thats why I felt flush() will be correct here.这就是为什么我觉得flush()在这里是正确的。 That is I open file once outside loop and only flush inside the loop.那就是我在循环外打开文件一次,只在循环内flush No need to open file in each iteration.无需在每次迭代中打开文件。

Why w+ and a+ gives error?为什么 w+ 和 a+ 会出错?

Because the file reader is pointed at the end of the file, where there's no json object to read因为文件阅读器指向文件末尾,这里没有 json object 可以读取

its contents are weird它的内容很奇怪

Seems like you're not resetting the file to an actual valid JSON object throughout your tests, and so you've managed to clear the file, read nothing, maybe write some other object, clear it again, then append one or two objects to it, etc etc. Seems like you're not resetting the file to an actual valid JSON object throughout your tests, and so you've managed to clear the file, read nothing, maybe write some other object, clear it again, then append one or two objects to它等等等等

Keep it simple.把事情简单化。 Start over重来

filename = "data.json"
with open(filename) as f:
    data = json.load(f)

data["foo"] = "bar"

with open(filename, "w") as f:
    json.dump(data, f)

You have to think in terms of what the operations do to a file when they open it:您必须考虑打开文件时操作对文件所做的操作:

  • r and r+ open a file for reading. rr+打开一个文件进行读取。 This means that the contents of the file is intact, and the file pointer is the beginning of the file.这意味着文件的内容是完整的,文件指针是文件的开头。 The entire file is visible to the reader.整个文件对读者可见。 After reading, the file pointer will be at the end, meaning that you're effectively appending at that point.阅读后,文件指针将位于末尾,这意味着您在该点有效地追加。
  • w and w+ open a file for writing. ww+打开一个文件进行写入。 That means that the contents of the file is truncated.这意味着文件的内容被截断。 There is nothing to be read in, since the original contents is destroyed.没有什么可以读入的,因为原始内容被破坏了。
  • a and a+ open the file for appending. aa+打开文件进行追加。 The contents of the file are unchanged.文件内容不变。 However, the file pointer is at the end, so a reader will see no data and raise an error.但是,文件指针位于末尾,因此阅读器将看不到任何数据并引发错误。

The correct way to do this is to open the file twice, and use with blocks to do it:这样做的正确方法是打开文件两次,并使用with块来做到这一点:

with open('dict_file.json', 'r') as f:
    a = json.load(f)

# you don't need the file to be open here
a = {'key': 'value'}

with open('dict_file.json', 'w') as f:
    json.dump(a, f)

You might be tempted to try to open the file in read-write mode ( r+ ), read it, then rewind it, so the pointer returns to the beginning, and then overwrite.您可能很想尝试以读写模式( r+ )打开文件,读取它,然后倒回它,这样指针就会回到开头,然后覆盖。 There are two reasons not to do this:不这样做的原因有两个:

  • Not every stream is rewindable并非每个 stream 都是可倒带的
  • If the contents of the file decreases in size, you will end up with trash at the end.如果文件内容的大小减小,最后您将得到垃圾。 You would need to truncate to the current pointer after writing, which is an unnecessary layer of complexity您需要在写入后截断为当前指针,这是不必要的复杂层

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM