Python json.load是否效率低下?
我正在查看Python json.load是否效率低下?,python,json,Python,Json,我正在查看json模块的源代码,试图回答另一个问题,这时我发现了一些奇怪的东西。除去docstring和一大堆关键字参数,json.load的源代码如下: def load(fp): return loads(fp.read()) 这一点也不像我预料的那样。如果json.load不能避免一次读取整个文件的开销,那么它比json.load(f.read())节省几个字符的源代码的唯一优势是什么?它为什么会存在?为什么它得到的是短名称,而不是loads得到的是loads名称和loadf这样
json
模块的源代码,试图回答另一个问题,这时我发现了一些奇怪的东西。除去docstring和一大堆关键字参数,json.load
的源代码如下:
def load(fp):
return loads(fp.read())
这一点也不像我预料的那样。如果
json.load
不能避免一次读取整个文件的开销,那么它比json.load(f.read())
节省几个字符的源代码的唯一优势是什么?它为什么会存在?为什么它得到的是短名称,而不是loads
得到的是loads
名称和loadf
这样的名称?我能想到原因(例如复制pickle
接口),但有人能提供权威的答案而不是猜测吗?尽管期待json是很自然的事。load()
做得更好,正如评论中提到的,但它不能保证做到这一点。这纯粹是推测,但如果我是Python维护人员,我会设计简单且维护开销最小的模块
Python标准库json
模块在速度和内存使用方面都不是最优的。对于不同的最佳点,有许多替代JSON读取实现,其中一些具有Python绑定,例如:
替代JSON实现源于以高效方式处理流和/或大量数据的必要性。可以肯定地说,从文件读取JSON虽然很重要,但不是JSON序列化的主要用例。因此,从文件实现高效的JSON加载并不是那么有趣,除非是在特殊情况下(有更有效的方法将大型数据结构序列化到磁盘) 然而,概括这个概念可能会引入一些有用的方面(例如,来自网络流的JSON反序列化,或者来自管道的渐进式JSON反序列化) 然后我们要寻找的是一个流式解析器(例如,像用于XML的SAX)。是一个常见的语法分析器,并且有很多方法可供使用
也可以看到这个问题的最上面的答案:我认为你的
pickle
想法不仅仅是猜测。json
模块文档中说,“json
公开了标准库marshal
和pickle
模块用户熟悉的API”,这强烈表明这是有意的。当然可能还有另一个原因。你为什么认为它效率低下?最终必须读取整个文本,因此执行单个读取
可以最大限度地减少I/O时间。此外,如果文件的文本不能保留在RAM中,那么几乎可以肯定结果不会保留在RAM中。拥有所有可用的文本可以避免在解析过程中处理问题,这可能会显著加快解析速度。如果你想发送千兆字节的数据,你无论如何都不应该使用json
,所以我看不出这个选择有什么错。@Bakuriu然而,如果字符串占用了约50%的内存,而解析的对象占用了约75%的内存,那么load
(如上实现)将失败。另一方面,逐块解析文件也可以。所以它在内存方面效率很低。虽然有点抽象。谁在和这么大的JSON一起工作?@怪怪的,这是我的观点。如果字符串占用了约50%的内存,则不应使用json
,而应使用更高效的编码。事实上,你不应该试图解码占用那么多RAM的对象,因为一个~75%RAM大小的对象无论如何都会让计算机交换很多东西。@Bakuriu:我知道这一点。但是,它没有回答为什么存在json.load
或者是否“应该”使用它的问题。我提出了一系列的理由来解释为什么load
可以这样实现,但是它们都是推测性的,没有一个能回答我是否应该和如何强烈地喜欢它而不是load(f.read())
“从文件中实现一个高效的JSON加载并没有那么有趣”——不过,如果read()的话,这会很有趣
从二进制模式文件返回一个类似字节序列的对象,它只是文件(部分)只读内存映射的写时拷贝包装器:-),这确实很有趣,尽管我怀疑它在字符串编码上会失败。数据blob是base64,常规字符串是UTF-8,两者都不是很有用。