为什么json.loads比ast.literal_eval快一个数量级?
在回答了有关如何解析包含浮点数数组的文本文件的问题之后,我运行了以下基准测试:
import timeitimport random
line = [random.random() for x in range(1000)]
n = 10000
json_setup = 'line = "{}"; import json'.format(line)
json_work = 'json.loads(line)'
json_time = timeit.timeit(json_work, json_setup, number=n)
print "json: ", json_time
ast_setup = 'line = "{}"; import ast'.format(line)
ast_work = 'ast.literal_eval(line)'
ast_time = timeit.timeit(ast_work, ast_setup, number=n)
print "ast: ", ast_time
print "time ratio ast/json: ", ast_time / json_time
我多次运行此代码,并始终得到以下结果:
$ python json-ast-bench.py json: 4.3199338913
ast: 28.4827561378
time ratio ast/json: 6.59333148483
因此,似乎json
比ast
此用例快了一个数量级。
使用Python 2.7.5+和Python 3.3.2+的结果相同。
- 为什么json.loads这么快?这个问题似乎暗示ast在输入数据(双引号或单引号)方面更灵活
- 在某些使用案例中
ast.literal_eval
,json.loads
尽管速度较慢,但我还是更愿意使用它吗?
无论如何,如果性能很重要,我建议您使用UltraJSON(正是我在工作中使用的,比使用相同的迷你基准的json快约4倍)。
回答:
这两个函数正在解析完全不同的语言-
JSON和Python文字语法。*如前所述literal_eval
:
提供的字符串或节点只能由以下Python文字结构组成:字符串,字节,数字,元组,列表,字典,集合,布尔值和
None
。
相比之下,JSON仅处理双引号的JavaScript字符串文字(与Python的*),对象(大致相当于dict),数组(大致等于列表),JavaScript布尔值(与Python不同)和null
。
这两种语言碰巧有重叠的事实并不意味着它们是同一语言。
为什么要
json.loads
这么快?
由于Python文字语法是一种比JSON更复杂,功能更强大的语言,因此解析起来可能会更慢。而且,可能更重要的是,由于Python文字语法不打算用作数据交换格式(实际上,它
不 应该专门用于该格式),因此没有人会为加快数据交换速度而付出很多努力。****
这个问题似乎暗示ast在输入数据(双引号或单引号)方面更灵活
那,原始字符串文字,以及Unicode vs. bytes字符串文字,以及复数,集合和JSON无法处理的所有其他内容。
在某些情况下,尽管速度较慢,但我更愿意在json.loads上使用ast.literal_eval?
是。当您想解析Python文字时,应使用ast.literal_eval
。(或者,更好的是,重新考虑您的设计,以便您不想解析Python文字…)
*这是一个模糊的术语。例如,-2
不是Python中的文字,而是运算符表达式,但literal_eval
可以处理它。当然,元组/列表/字典/集合显示不是文字,但是literal_eval
可以处理它们,除了理解也是显示,并且literal_eval
不能处理它们。ast
模块中的其他功能可以帮助您找出真正的字面值和非字面值,例如ast.dump(ast.parse("expr"))
。
**例如,"\q"
是JSON中的错误。
***从技术上讲,JSON仅处理一种“数字”类型,即浮点数。但是Python的json
模块将不带小数点或指数的数字解析为整数,在许多其他语言的JSON模块中也是如此。
****如果您错过了蒂姆·彼得斯(Tim Peters)对以下问题的评论:“
ast.literal_eval
使用率太低,没有人觉得值得花时间(和工作,和工作)来加速它。相反,JSON库通常用于解析千兆字节的数据。”
以上是 为什么json.loads比ast.literal_eval快一个数量级? 的全部内容, 来源链接: utcz.com/qa/415981.html