与open一起使用,为什么'rb'用于阅读json可以工作,而'rb'用于写json却不行?

sxpgvts3  于 2023-10-21  发布在  其他
关注(0)|答案(4)|浏览(113)

我注意到,当使用with open读取json时,使用rrb参数返回相同的结果。

with open('something.json', 'rb') as f # 'r' returns the same thing
    t1 = json.load(f)

然而,当我用wb写一个json时,我得到一个错误:

with open('something.json', 'wb') as f:
  json.dump(some_dict, f)

TypeError:需要类似字节的对象,而不是'str'
但是w工作得很好。为什么会这样呢?

xzlaal3s

xzlaal3s1#

当以只读二进制模式rb打开文件时,f.read()函数返回字节而不是字符串(对于文本模式),这两者对于json.load函数参数都是可以接受的
当以只写二进制模式wb打开文件时,f.write()函数只支持类似字节的对象作为参数,而不是str。因此,当json.dump调用它并试图将字符串值传递给f.write时,它将引发上面看到的异常。

nszi6y05

nszi6y052#

发生这种情况是因为你没有在JSON上以二进制形式写入,尝试使用json.dumps(some_dict)将字典转换为JSON文件,然后使用some_dict.encode('utf-8')以二进制形式写入。大概是这样的:

json_data = json.dumps(data)
with open('something.json', 'wb') as f:
f.write(json_data.encode('utf-8'))
hvvq6cgz

hvvq6cgz3#

从Python 3.6开始,json模块尝试在阅读JSON时自动检测二进制文件的编码。支持UTF-8、UTF-16或UTF-32。
但是,这在写作时不起作用。没有办法自动检测您在编写时想要使用的编码。json可以做一个假设,就像open在不指定编码的情况下以文本模式打开文件时所做的那样,但是权衡是不同的。
如果json在写入二进制文件时采用UTF-8编码(或任何其他编码),那么您可能最终会阅读UTF-32并写入UTF-8,而不会注意到编码的变化,直到其他需要UTF-32的代码中断。这对于open来说不是什么问题,因为open在阅读或写入时做出了相同的假设,而不是在阅读时尝试自动检测编码。
由于自动检测是不可能的,并且假设编码容易出错,因此json要求您在编写时给予一个文本文件。

3phpmpom

3phpmpom4#

由于json.loadjson.loads是给定的要检查的数据,所以当给定二进制时,它们会尝试猜测数据的编码。但在转储数据时它不能这样做,因为没有任何东西可以检查。因此,缺乏对称性。您可以给予一个二进制文件给读取器,冒着它会错误地猜测编码的风险。但不是作者。它只适用于字符串,你需要自己处理编码。
就我个人而言,我不会相信编码猜测者,并且总是以“r”模式打开,并使用显式编码。

相关问题