การผูกสนิมสำหรับ Python รวมถึงเครื่องมือสำหรับการสร้างโมดูลส่วนขยาย Python ดั้งเดิม นอกจากนี้ยังรองรับการเรียกใช้และการโต้ตอบกับโค้ด Python จากไบนารี่ของ Rust
คู่มือผู้ใช้: เสถียร | หลัก
เอกสาร API: เสถียร | หลัก
ต้องใช้สนิม 1.63 หรือสูงกว่า
PyO3 รองรับการแจกแจง Python ต่อไปนี้:
คุณสามารถใช้ PyO3 เพื่อเขียนโมดูล Python ดั้งเดิมใน Rust หรือเพื่อฝัง Python ในไบนารี่ของ Rust ส่วนต่อไปนี้จะอธิบายแต่ละส่วนตามลำดับ
PyO3 สามารถใช้เพื่อสร้างโมดูล Python ดั้งเดิมได้ วิธีที่ง่ายที่สุดในการลองใช้ครั้งแรกคือใช้ maturin
maturin
เป็นเครื่องมือสำหรับสร้างและเผยแพร่แพ็คเกจ Python ที่ใช้ Rust โดยมีการกำหนดค่าน้อยที่สุด ขั้นตอนต่อไปนี้จะติดตั้ง maturin
ใช้เพื่อสร้างและสร้างแพ็คเกจ Python ใหม่ จากนั้นเปิดใช้ Python เพื่อนำเข้าและเรียกใช้ฟังก์ชันจากแพ็คเกจ
ขั้นแรก ทำตามคำสั่งด้านล่างเพื่อสร้างไดเร็กทอรีใหม่ที่มี Python virtualenv
ใหม่ และติดตั้ง maturin
ลงใน virtualenv โดยใช้ตัวจัดการแพ็คเกจของ Python pip
:
# (replace string_sum with the desired package name)
$ mkdir string_sum
$ cd string_sum
$ python -m venv .env
$ source .env/bin/activate
$ pip install maturin
ยังอยู่ในไดเร็กทอรี string_sum
นี้ ตอนนี้รัน maturin init
สิ่งนี้จะสร้างซอร์สแพ็คเกจใหม่ เมื่อได้รับตัวเลือกของการโยงที่จะใช้ ให้เลือกการโยง pyo3:
$ maturin init
✔ ? What kind of bindings to use ? · pyo3
Done ! New project created string_sum
ไฟล์ที่สำคัญที่สุดที่สร้างโดยคำสั่งนี้คือ Cargo.toml
และ lib.rs
ซึ่งจะมีลักษณะคร่าวๆ ดังต่อไปนี้:
Cargo.toml
[ package ]
name = " string_sum "
version = " 0.1.0 "
edition = " 2021 "
[ lib ]
# The name of the native library. This is the name which will be used in Python to import the
# library (i.e. `import string_sum`). If you change this, you must also change the name of the
# `#[pymodule]` in `src/lib.rs`.
name = " string_sum "
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = [ " cdylib " ]
[ dependencies ]
pyo3 = { version = " 0.23.3 " , features = [ " extension-module " ] }
src/lib.rs
use pyo3 :: prelude :: * ;
/// Formats the sum of two numbers as string.
# [ pyfunction ]
fn sum_as_string ( a : usize , b : usize ) -> PyResult < String > {
Ok ( ( a + b ) . to_string ( ) )
}
/// A Python module implemented in Rust. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
# [ pymodule ]
fn string_sum ( m : & Bound < ' _ , PyModule > ) -> PyResult < ( ) > {
m . add_function ( wrap_pyfunction ! ( sum_as_string , m ) ? ) ? ;
Ok ( ( ) )
}
สุดท้ายให้รัน maturin develop
สิ่งนี้จะสร้างแพ็คเกจและติดตั้งลงใน Python virtualenv ที่สร้างและเปิดใช้งานก่อนหน้านี้ แพ็คเกจก็พร้อมใช้งานจาก python
:
$ maturin develop
# lots of progress output as maturin runs the compilation...
$ python
>>> import string_sum
>>> string_sum.sum_as_string(5, 20)
' 25 '
หากต้องการเปลี่ยนแปลงแพ็คเกจ เพียงแก้ไขซอร์สโค้ด Rust จากนั้นรัน maturin develop
อีกครั้งเพื่อคอมไพล์ใหม่
หากต้องการเรียกใช้ทั้งหมดนี้เป็นการคัดลอกและวางเพียงครั้งเดียว ให้ใช้สคริปต์ทุบตีด้านล่าง (แทนที่ string_sum
ในคำสั่งแรกด้วยชื่อแพ็คเกจที่ต้องการ):
mkdir string_sum && cd " $_ "
python -m venv .env
source .env/bin/activate
pip install maturin
maturin init --bindings pyo3
maturin develop
หากคุณต้องการรัน cargo test
หรือใช้โปรเจ็กต์นี้ในพื้นที่ทำงานของ Cargo และกำลังประสบปัญหาตัวเชื่อมโยง มีวิธีแก้ไขปัญหาบางประการในคำถามที่พบบ่อย
เช่นเดียวกับ maturin
คุณสามารถสร้างโดยใช้ setuptools-rust
หรือด้วยตนเองได้ ทั้งสองให้ความยืดหยุ่นมากกว่า maturin
แต่ต้องมีการกำหนดค่าเพิ่มเติมเพื่อเริ่มต้น
หากต้องการฝัง Python ลงในไบนารี่ของ Rust คุณต้องแน่ใจว่าการติดตั้ง Python ของคุณมีไลบรารีที่ใช้ร่วมกัน ขั้นตอนต่อไปนี้สาธิตวิธีการตรวจสอบสิ่งนี้ (สำหรับ Ubuntu) จากนั้นให้ตัวอย่างโค้ดที่รันล่าม Python แบบฝัง
วิธีติดตั้งไลบรารี่ที่ใช้ร่วมกันของ Python บน Ubuntu:
sudo apt install python3-dev
หากต้องการติดตั้งไลบรารีที่ใช้ร่วมกันของ Python บนการกระจายตาม RPM (เช่น Fedora, Red Hat, SuSE) ให้ติดตั้งแพ็คเกจ python3-devel
เริ่มโปรเจ็กต์ใหม่ด้วย cargo new
และเพิ่ม pyo3
ลงใน Cargo.toml
ดังนี้:
[ dependencies . pyo3 ]
version = " 0.23.3 "
features = [ " auto-initialize " ]
ตัวอย่างโปรแกรมที่แสดงค่า sys.version
และชื่อผู้ใช้ปัจจุบัน:
use pyo3 :: prelude :: * ;
use pyo3 :: types :: IntoPyDict ;
use pyo3 :: ffi :: c_str ;
fn main ( ) -> PyResult < ( ) > {
Python :: with_gil ( |py| {
let sys = py . import ( "sys" ) ? ;
let version : String = sys . getattr ( "version" ) ? . extract ( ) ? ;
let locals = [ ( "os" , py . import ( "os" ) ? ) ] . into_py_dict ( py ) ? ;
let code = c_str ! ( "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'" ) ;
let user : String = py . eval ( code , None , Some ( & locals ) ) ? . extract ( ) ? ;
println ! ( "Hello {}, I'm Python {}" , user , version ) ;
Ok ( ( ) )
} )
}
คู่มือนี้มีส่วนที่มีตัวอย่างมากมายเกี่ยวกับหัวข้อนี้
built
เป็น PyDict
เรายินดีให้ทุกคนมีส่วนร่วมใน PyO3! การสนับสนุนโครงการมีหลายวิธี เช่น
บันทึกที่มีส่วนร่วมและคู่มือสถาปัตยกรรมของเรามีแหล่งข้อมูลเพิ่มเติม หากคุณต้องการสละเวลาเป็นอาสาสมัครให้กับ PyO3 และกำลังค้นหาว่าจะเริ่มต้นจากตรงไหน
หากคุณไม่มีเวลามีส่วนร่วมแต่ยังคงต้องการสนับสนุนความสำเร็จในอนาคตของโครงการ ผู้ดูแลของเราบางคนมีหน้าผู้สนับสนุน GitHub:
PyO3 ได้รับใบอนุญาตภายใต้ใบอนุญาต Apache-2.0 หรือใบอนุญาต MIT ตามตัวเลือกของคุณ
Python ได้รับอนุญาตภายใต้ใบอนุญาต Python
เว้นแต่คุณจะระบุไว้เป็นอย่างอื่นอย่างชัดเจน การสนับสนุนใดๆ ที่ส่งโดยเจตนาเพื่อรวมไว้ใน PyO3 โดยคุณ ตามที่กำหนดไว้ในใบอนุญาต Apache จะต้องได้รับใบอนุญาตแบบคู่ตามที่กล่าวไว้ข้างต้น โดยไม่มีข้อกำหนดหรือเงื่อนไขเพิ่มเติมใดๆ