python - `ast.literal_eval` 的最快实现
问题描述
str
我有一些bytes
可以通过ast.literal_eval
.
(它由一个dicts列表组成,其中dict键是字符串,值是字符串,int或float。但也许这个问题对于任何可以通过解析的字符串都是通用的ast.literal_eval
。)
它很大:~22MB 未压缩。
解析它的最快方法是什么?
当然我可以使用ast.literal_eval
,但这似乎很慢。标准eval
稍快(有趣的是,但可能与预期的一样,取决于您对 Python 的了解程度;请参阅 的实现ast.literal_eval
)但仍然很慢。
相比之下,当我将相同的数据序列化为 JSON,然后加载 JSON ( )json.loads
时,这要快得多 (>10x)。所以这表明原则上应该可以同样快地解析它。
一些统计数据:
Gunzip + read time: 0.15111494064331055
Size: 22035943
compile: 3.1023156170000004
parse: 3.3381092380000004
eval: 3.0252232049999996
ast.literal_eval: 3.765798232
json.loads: 0.2657175249999994
可以找到此基准脚本以及生成此类虚拟文本文件的脚本:here
(也许答案是:“这需要更快的 C 实现;还没有人实现过”)
好的,发布后,我发现了一些相关问题。虽然我没有通过谷歌找到它们(也许我的搜索词“faster literal_eval”很糟糕)。
这部分回答了这个问题。
解决方案
因此,据我所知,目前不存在比ast.literal_eval
(嗯,eval
它本身更快,但不安全)的实现。
所以我实现了我自己的简单实现,它将文字 Python 代码转换为等效的二进制 Pickle 数据。因此,对于某些字节,您将使用,data
而不是,并获得 5.5 倍的加速。ast.literal_eval(data.decode("utf8"))
pickle.loads(py_to_pickle(data))
回购在这里。这是 C++ 中一个非常直接的实现,您可以轻松地直接使用它ctypes
(repo 中有一个示例)。
新统计:
Gunzip + read time: 0.1663219928741455
Size: 22540270
py_to_pickle: 0.539439306
pickle.loads+py_to_pickle: 0.7234611099999999
compile: 3.3440755870000003
parse: 3.6302585899999995
eval: 3.306765757000001
ast.literal_eval: 4.056752016000003
json.loads: 0.3230752619999997
pickle.loads: 0.1351051709999993
marshal.loads: 0.10351717500000035
推荐阅读
- c++ - C++20 概念:元素可迭代概念
- typescript - 如何为可区分的联合类型数组编写类型保护?
- uno-platform - 如何获取 uri 以包含在 Uno 平台中的资产?
- python - 在 Python 中使用随机函数时每次都取零
- css - 如果设置了 -webkit-box 显示属性,则第一个字母不起作用
- r - 如何使用 mutate 和 ifelse 处理 NA 的存在?
- sql-server - 使用条件运算符返回记录的 T-SQL SELECT 语句
- javascript - Express 服务器,最多可创建 2 个子/工作进程
- c# - Linq 查询从 FakeXrmEasy 上下文返回错误记录
- python - 我将如何检测用户活动?| 不和谐.py