이번 포스팅에서는 Rust로 작성한 코드를 Python에서 사용하는 방법에 대해 설명하겠습니다.
Install maturin/PyO3
먼저, python 가상 환경을 만들고 rust로작성한 코드를 python package로 빌드할 수 있는 tool을 설치해 줍니다.
$ pip install maturin
Create Project
다음으로 설치한 tool을 사용하여 프로젝트를 생성합니다.
다음 명령을 입력하면 PyO3를 빌드 시스템으로 하는 프로젝트를 생성합니다.
$ maturin init -b pyo3
Implement Library Crate
이제 원하는 rust 코드를 작성합니다.
use pyo3::prelude::*;
use std::fs::File;
use std::io::{Read};
#[pyfunction]
fn parse_bin(file_name: &str) -> PyResult<Vec<(u8, u8, u16, u32)>> {
let mut file = File::open(file_name).map_err(|e| PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string()))?;
let mut buffer = [0u8; 8];
let mut results = Vec::new();
loop {
let bytes_read = file.read(&mut buffer).map_err(|e| PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string()))?;
if bytes_read == 0 {
break;
}
if bytes_read != 8 {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>("Invalid file format"));
}
let part1 = buffer[0];
let part2 = buffer[1];
let part3 = u16::from_le_bytes([buffer[2], buffer[3]]);
let part4 = u32::from_le_bytes([buffer[4], buffer[5], buffer[6], buffer[7]]);
results.push((part1, part2, part3, part4));
}
Ok(results)
}
#[pymodule]
fn python_ffi(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(parse_bin, m)?)?;
Ok(())
}
저는 간단하게 바이너리 파일 처리하는 것을 만들어 보았습니다.
#[pyfunction] attribute를 추가하면 PyO3가 python에서 호출할 수 있는 코드로 만들어 주고, #[pymodule] attribute를 추가하면 python module로 만들어 줍니다.
Build
이제 이 코드를 다음 명령으로 빌드해 줍니다.
Build는 2가지 모드로 가능합니다.
1. 개발 모드
$ maturin develop
2. 배포 모드
$ maturin build --release
개발 시에는 빠른 개발과 디버깅을 위해 개발 모드로 빌드를 하고, 완성 후 배포 시에는 성능을 위해 배포 모드로 빌드를 하면 됩니다.
사용하는 환경에 따라 개발 환경은 설정되어 있어야 합니다.
Implement Python Code
이제 python에서 사용하기 위한 코드를 작성해 봅니다.
먼저, rust로 작성한 모듈을 설치합니다.
$ pip install target/wheels/<MODULE>.whl
이제 파이썬 코드에서 모듈을 사용할 수 있습니다.
from python_ffi import parse_bin
result = parse_bin('test.bin')
위와 같이 일반 파이썬 모듈 호출하듯이 사용하면 됩니다.
Wrap Up
이번에는 rust로 작성한 코드를 python에서 사용하는 방법에 대해 살펴보았습니다.
방법 자체는 매우 간단하니 GIL 등의 제약으로 인해 성능이나 보안 측면에서 개선이 필요할 때 사용해보시면 좋을 것 같습니다.
'Python' 카테고리의 다른 글
[Flet] Getting Started (0) | 2024.07.12 |
---|---|
[Typer] Python으로 CLI App 만들기 (0) | 2024.03.30 |
[Python] PyPI에 패키지 배포하기 (3) | 2024.03.16 |
[FastAPI] Getting Started (0) | 2023.09.13 |
[PyQt6] Save and Load Settings using QSettings (0) | 2023.04.06 |
댓글