روابط الصدأ لـ Python، بما في ذلك أدوات إنشاء وحدات امتداد Python الأصلية. يتم أيضًا دعم التشغيل والتفاعل مع كود Python من ملف Rust الثنائي.
دليل المستخدم: مستقر | رئيسي
وثائق واجهة برمجة التطبيقات: مستقرة | رئيسي
يتطلب Rust 1.63 أو أكبر.
يدعم PyO3 توزيعات بايثون التالية:
يمكنك استخدام 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
لإعادة الترجمة.
لتشغيل كل هذا كنسخة ولصق واحدة، استخدم البرنامج النصي bash أدناه (استبدل 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
أو استخدام هذا المشروع في مساحة عمل الشحن وتواجه مشكلات في الرابط، فهناك بعض الحلول في الأسئلة المتداولة.
كما هو الحال مع 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، يجب أن تكون مرخصة بشكل مزدوج على النحو الوارد أعلاه، دون أي شروط أو أحكام إضافية.