我注意到,当使用with open
读取json时,使用r
或rb
参数返回相同的结果。
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
工作得很好。为什么会这样呢?
4条答案
按热度按时间xzlaal3s1#
当以只读二进制模式
rb
打开文件时,f.read()
函数返回字节而不是字符串(对于文本模式),这两者对于json.load函数参数都是可以接受的当以只写二进制模式
wb
打开文件时,f.write()
函数只支持类似字节的对象作为参数,而不是str
。因此,当json.dump调用它并试图将字符串值传递给f.write
时,它将引发上面看到的异常。nszi6y052#
发生这种情况是因为你没有在JSON上以二进制形式写入,尝试使用
json.dumps(some_dict)
将字典转换为JSON文件,然后使用some_dict.encode('utf-8')
以二进制形式写入。大概是这样的: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
要求您在编写时给予一个文本文件。3phpmpom4#
由于
json.load
和json.loads
是给定的要检查的数据,所以当给定二进制时,它们会尝试猜测数据的编码。但在转储数据时它不能这样做,因为没有任何东西可以检查。因此,缺乏对称性。您可以给予一个二进制文件给读取器,冒着它会错误地猜测编码的风险。但不是作者。它只适用于字符串,你需要自己处理编码。就我个人而言,我不会相信编码猜测者,并且总是以“r”模式打开,并使用显式编码。