#serde_json #dict
너무 큰 JSON 을 파이썬에서 처리할 때 고민.
너무 느리다.
메모리를 너무 많이 먹는다.
그래서 orjson 라이브러리를 사용하곤 하는데
결국 json 데이터를 핸들링하는 주체는 파이썬이고
키-값 데이터를 loop 하면서 뭔가 조작을 한다는건 부담일 수 있다.
이걸 Rust 로 보내서 동시성을 확보면 어떨까.
# maturin project
>> maturin new calc_test
>> cd calc_test
이러면 정확히 아래와 같은 트리구조의 디렉토리가 생성된다.
Cargo.toml 을 먼저 살펴보고,
[package]
name = "calc_test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "calc_test"
crate-type = ["cdylib"]
[dependencies]
pyo3 = "0.21.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
디펜던시를 잘 봐둬야 한다.
다음으로 pyroject.toml 을 보면,
[build-system]
requires = ["maturin>=1.6,<2.0"]
build-backend = "maturin"
[project]
name = "calc_test"
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dynamic = ["version"]
[tool.maturin]
features = ["pyo3/extension-module"]
이 또한 자동으로 완성된다.
이제 로직을 하나 만들건데, src/lib.rs 에서 진행한다.
json 형태의 string 데이터를 가져와서
특정 키를 이용해 값을 취하고
이를 이용해 간단한 덧셈 로직을 구현해본다.
use pyo3::prelude::*;
use pyo3::exceptions::PyValueError;
use serde_json::Value;
#[pyfunction]
fn calculate_digit(json_data: &str, key1: &str, key2: &str) -> PyResult<f64> {
let data: Value = serde_json::from_str(json_data).unwrap();
let value1 = data[key1]
.as_f64()
.ok_or_else(|| {
PyValueError::new_err(format!("Error! {} : Key '{}' not found or not a number", key1, key1))
})?;
let value2 = data.get(key2)
.and_then(
|value| {
value.as_f64()
}
)
.ok_or_else(
|| {
PyValueError::new_err(format!("Error! {} : Key '{}' not found or not a number", key2, key2))
}
);
let rate = (value1 + value2.unwrap()) / 2.0;
Ok(rate)
}
#[pymodule]
fn calc_test(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(calculate_digit, m)?)?;
Ok(())
}
보는것처럼 간단하다.
키로 값을 받아서 덧셈 & 나눗셈을 하고 그 결과를 반환한다.
다음 명령어로 whl 파일을 만든다.
>> maturin build --release
이러면 target 디렉토리에 whl 파일이 생성되는데
해당 위치를 찍고
바로 pip 로 설치를 한다.
예를 들어,
>> pip install /path/calc_test/target/wheels/calc_test-0.1.0-cp38-cp38-macosx_10_12_x86_64.whl --force-reinstall
이러면 설치는 완료!
바로 쥬피터 꺼내서
import os
import orjson
import json
from calc_test import calculate_digit
large_json_data = {
"key1": 5.0,
"key2": 3.0,
"key3": 5.0,
"key4": 3.0,
"key5": 5.0,
"key6": 3.0,
}
# json_str = json.dumps(large_json_data)
json_str = orjson.dumps(large_json_data).decode()
try:
rate = calc_test.calculate_digit(json_str, "key1", "key2")
print(f"Calculated rate: {rate}")
except ValueError as e:
print(f"Error calculating rate: {e}")
이러면 거~~대한 json 파일 핸들링도 좀 더 가볍게 할 수 있다.