Faster JSON - orjson | Python 主题月

本文正在参加「Python主题月」,详情查看 活动连接python

微信公众号搜索【程序媛小庄】,Rest cannot be enjoyed by lazy people~git

前言

JSON使用的越多就越可能遇到JSON编码或者解码的瓶颈,Python的内置json库虽然也很好用可是也有不少其余更快的JSON库可使用,可是具体选择哪个或者哪种须要根据具体状况,没有一种标准的规则衡量哪种JSON最好或者最快,由于不一样的项目有不一样的需求,有的注重安全有的注重速度更快,本文介绍更快的json-orjsongithub

orjson简介

orjson是一个更加快速的Python JSON库,经过基准测试发现比标准json库和rapidjson的速度更快,能够序列化dataclass datetime numpy UUIDjson或者rapidjson相比orjson序列化获得的结果是bytes类型而不是json格式的str类型,序列化时不会将unicode转换成ASCII,须要注意的是,orjson不提供dump/load方法实现对file-like对象进行序列化和反序列化。更多关于orjson的使用请参考官方文档web

json rapidson和orjson速度对比

下面是json rapidjson orjson进行的基准测试代码以及结果。json

import json
import orjson
import rapidjson
import time

m = {
    "timestamp": 1556283673.1523004,
    "task_uuid": "0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7",
    "task_level": [1, 2, 1],
    "action_status": "started",
    "action_type": "main",
    "key": "value",
    "another_key": 123,
    "and_another": ["a", "b"],
}


def benchmark(module_name, dumps):
    start = time.time()
    for i in range(100000):
        dumps(m)
    print(module_name, time.time() - start)


benchmark('json', json.dumps)
benchmark('rapidjson', rapidjson.dumps)
benchmark("orjson", lambda s: str(orjson.dumps(s), "utf-8"))  # orjson只能输出bytes
复制代码

而且结果以下,orjson即便须要额外的Unicode解码也是最快的,可是并不表明博主必定推荐您使用orjson,须要根据实际状况进行选择哦~:api

json 1.1019978523254395
rapidjson 0.25800156593322754
orjson 0.0859987735748291
复制代码

orjson基本使用

orjson安装

安装命令很是简单:pip install orjson浏览器

须要注意的是,在Linux环境中使用pip命令安装时pip版本须要大于19.3,所以在安装orjson时能够先更新pip版本。安全

orjson基本使用

序列化-dumps

和Python标准JSON库json相比最大的不一样在于orjson.dumps返回的结果的是bytesjson.dumps返回的结果是strsort_keys参数被option=orjson.OPT_SORT_KEYS代替,indent参数被option=orjson.OPT_INDENT_2代替而且不支持其余indent等级。微信

def dumps( __obj: Any, default: Optional[Callable[[Any], Any]] = ..., option: Optional[int] = ..., ) -> bytes: ...
    
# 序列化
import orjson

m = {
    "timestamp": 1556283673.1523004,
    "task_uuid": "0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7",
    "task_level": [1, 2, 1],
    "action_status": "started",
    "action_type": "哈哈",
    "key": "value",
    "another_key": 123,
    "and_another": ["a", "b"],
}


res = orjson.dumps(m)
print(res)  
# b'{"timestamp":1556283673.1523004,"task_uuid":"0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7","task_level":[1,2,1],"action_status":"started","action_type":"\xe5\x93\x88\xe5\x93\x88","key":"value","another_key":123,"and_another":["a","b"]}'
复制代码

反序列化-loads

loads方法将bytes类型的JSON格式数据反序列化称为Python示例对象。markdown

print(orjson.loads(res))
复制代码

float int str类型的序列化和反序列化

float

orjson在序列化和反序列化双精度浮点数时不会损失精度,在json rapidjson中一样不会损失精度。orjson.dumps对序列化Nan,Infinity,-Infinity不兼容,会获得null的结果,可是json和rapidjson支持。

>>> import orjson, ujson, rapidjson, json
>>> orjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
b'[null,null,null]'
>>> rapidjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN,Infinity,-Infinity]'
>>> json.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN, Infinity, -Infinity]'
复制代码

int

orjson默承认以序列化和反序列化64-bits的证书,支持的范围是带符号的最小值(-9223372036854775807)到无符号的最大值(18446744073709551615),可是在某些场景下只支持53-bits的证书,好比web浏览器,对于不兼容的部分,dumps方法会抛出JSONEncodeError异常。

>>> import orjson
>>> orjson.dumps(9007199254740992)
b'9007199254740992'
>>> orjson.dumps(9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
>>> orjson.dumps(-9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
复制代码

str

orjson和UTF8具备严格的一致性,比Python的标准库json更为严格,json在序列化和反序列化时使用UTF-16进行代理,可是这是不可用的UTF8。若是orjson.dumps的参数传了一个不是UTF8的字符那么会抛出orjson.JSONEncodeError异常,若是orjson.loads()的参数收到了不可用的UTF8字符也会抛出一样的异常。

orjson和rapidjson和Python标准库json相比来讲,对于不符合规则的输入始终都会抛出相应的异常。

为了程序的健壮性,能够在反序列化时先将bytes类型编码成成UTF8格式。

>>> import orjson
>>> orjson.loads(b'"\xed\xa0\x80"')
JSONDecodeError: str is not valid UTF-8: surrogates not allowed
>>> orjson.loads(b'"\xed\xa0\x80"'.decode("utf-8", "replace"))
复制代码

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)

image.png

相关文章
相关标签/搜索