Python itu luar biasa. Kami mengatakan "pip install" dan kemungkinan besar pustaka yang diperlukan akan dikirimkan. Tetapi kadang-kadang jawabannya adalah: "kompilasi gagal", karena ada modul biner. Mereka menderita semacam rasa sakit di hampir semua bahasa modern, karena ada banyak arsitektur, sesuatu perlu dirakit untuk mesin tertentu, sesuatu perlu dihubungkan dengan perpustakaan lain. Secara umum, pertanyaan yang menarik, tetapi sedikit dipelajari: bagaimana mereka dapat dilakukan dan masalah apa yang ada? Dmitry Zhiltsov (
zaabjuda ) mencoba menjawab pertanyaan ini di MoscowPython Conf tahun lalu.
Di bawah potongan adalah versi teks dari laporan Dmitry. Mari kita bahas secara singkat kapan modul biner dibutuhkan, dan kapan lebih baik meninggalkannya. Mari kita bahas aturan yang harus diikuti saat menulisnya. Pertimbangkan lima opsi implementasi yang mungkin:
- Ekstensi C / C ++ asli
- Meneguk
- Cython
- Ctypes
- Karat
Tentang pembicara : Dmitry Zhiltsov telah berkembang selama lebih dari 10 tahun. Dia bekerja di CIAN sebagai arsitek sistem, yaitu, dia bertanggung jawab untuk solusi teknis dan pengaturan waktu. Dalam hidup saya, saya berhasil mencoba assembler, Haskell, C, dan selama 5 tahun terakhir saya telah aktif memprogram dengan Python.
Tentang perusahaan
Banyak yang tinggal di Moskow dan menyewa rumah mungkin tahu tentang CIAN. CYAN adalah 7 juta pembeli dan penyewa per bulan. Semua pengguna ini setiap bulan, menggunakan layanan kami, menemukan tempat tinggal.
Sekitar 75% orang Moskow tahu tentang perusahaan kami, dan ini sangat keren. Di St. Petersburg dan Moskow, kita secara praktis dianggap sebagai pelaku monopoli. Saat ini, kami mencoba memasuki daerah, dan oleh karena itu pembangunan telah tumbuh 8 kali selama 3 tahun terakhir. Ini berarti bahwa tim meningkat 8 kali, kecepatan pengiriman nilai ke pengguna meningkat 8 kali, yaitu. dari ide produk hingga bagaimana tangan seorang insinyur meluncurkan bangunan ke produksi. Kami belajar di tim besar kami untuk berkembang sangat cepat, dan sangat cepat memahami apa yang terjadi saat ini, tetapi hari ini kami akan berbicara sedikit tentang sesuatu yang lain.
Saya akan berbicara tentang modul biner. Sekarang hampir 50% perpustakaan Python memiliki beberapa jenis modul biner. Dan ternyata, banyak orang yang tidak mengenal mereka dan percaya bahwa ini adalah sesuatu yang transendental, sesuatu yang gelap dan tidak perlu. Dan orang lain menyarankan untuk menulis microservice terpisah dengan lebih baik dan tidak menggunakan modul biner.
Artikel akan terdiri dari dua bagian.
- Pengalaman saya: mengapa mereka dibutuhkan, kapan mereka paling baik digunakan, dan kapan tidak.
- Alat dan teknologi yang dengannya Anda dapat mengimplementasikan modul biner untuk Python.
Mengapa modul biner diperlukan?
Kita semua tahu betul bahwa Python adalah bahasa yang ditafsirkan. Ini hampir yang tercepat dari bahasa yang ditafsirkan, tetapi, sayangnya,
kecepatannya tidak selalu cukup untuk perhitungan matematika yang berat. Segera timbul pemikiran bahwa C akan lebih cepat.
Tapi Python memiliki satu lagi rasa sakit - itu adalah
GIL . Sejumlah besar artikel telah ditulis tentang dia dan laporan telah dibuat tentang cara untuk mengelilinginya.
Kita juga membutuhkan ekstensi biner untuk
menggunakan kembali logika . Misalnya, kami menemukan perpustakaan yang memiliki semua fungsi yang kami butuhkan, dan mengapa tidak menggunakannya. Artinya, Anda tidak perlu menulis ulang kode, kami hanya mengambil kode yang sudah jadi dan menggunakannya kembali.
Banyak orang percaya bahwa menggunakan ekstensi biner Anda dapat
menyembunyikan kode sumber . Pertanyaannya sangat, sangat kontroversial, tentu saja, dengan bantuan beberapa penyimpangan liar ini dapat dicapai, tetapi tidak ada jaminan 100%. Maksimum yang bisa Anda dapatkan adalah tidak membiarkan klien mendekompilasi dan melihat apa yang terjadi dalam kode yang Anda berikan.
Kapan ekstensi biner benar-benar dibutuhkan?
Tentang kecepatan dan Python sudah jelas - ketika beberapa fungsi bekerja sangat lambat dan menempati 80% waktu eksekusi semua kode, kami mulai berpikir untuk menulis ekstensi biner. Tetapi untuk membuat keputusan seperti itu, Anda harus mulai, seperti yang dikatakan oleh seorang pembicara terkenal, berpikir dengan otak Anda.
Untuk menulis ekstensi ekstensi, orang harus mempertimbangkan bahwa ini, pertama, akan panjang. Pertama, Anda perlu "menjilat" algoritme Anda, mis. lihat apakah ada tiang tembok.
Dalam 90% kasus, setelah memeriksa algoritma secara menyeluruh, kebutuhan untuk menulis beberapa ekstensi menghilang.
Kasus kedua di mana ekstensi biner benar-benar dibutuhkan adalah
penggunaan multi threading untuk operasi sederhana . Sekarang ini tidak begitu relevan, tetapi masih tetap ada di perusahaan berdarah, di beberapa integrator sistem, di mana Python 2.6 masih ditulis. Tidak ada sinkronisasi, dan bahkan untuk hal-hal sederhana, misalnya, mengunggah banyak gambar, multi-threading naik. Tampaknya pada awalnya ini tidak menimbulkan biaya jaringan apa pun, tetapi ketika kami mengunggah gambar ke buffer, GIL naas datang dan semacam rem dimulai. Seperti yang diperlihatkan oleh praktik, hal-hal seperti itu paling baik diselesaikan dengan menggunakan perpustakaan yang tidak diketahui Python.
Jika Anda perlu menerapkan beberapa protokol khusus, mungkin lebih mudah untuk membuat kode C / C ++ sederhana dan menghilangkan banyak rasa sakit. Saya melakukan ini di waktu saya di satu operator telekomunikasi, karena tidak ada perpustakaan yang siap pakai - saya harus menulis sendiri. Tapi saya ulangi, sekarang ini tidak terlalu relevan, karena ada asyncio, dan untuk sebagian besar tugas ini sudah cukup.
Tentang
operasi yang jelas
sulit, saya sudah katakan sebelumnya. Ketika Anda memiliki crash, matriks besar dan sejenisnya, masuk akal bahwa Anda perlu melakukan ekstensi ke C / C ++. Saya ingin mencatat bahwa beberapa orang berpikir bahwa kita tidak memerlukan ekstensi biner di sini, lebih baik untuk membuat layanan mikro dalam "
bahasa super cepat " dan mentransfer matriks besar melalui jaringan. Tidak, lebih baik tidak melakukannya.
Contoh lain yang baik ketika mereka dapat dan bahkan harus diambil adalah ketika Anda memiliki
logika modul yang sudah ada . Jika Anda memiliki modul atau pustaka Python di perusahaan Anda selama 3 tahun sudah, ada perubahan di dalamnya setahun sekali dan kemudian 2 baris, maka mengapa tidak membuatnya menjadi pustaka C normal jika ada sumber daya dan waktu gratis. Minimal, dapatkan peningkatan produktivitas. Dan juga akan ada pemahaman bahwa jika beberapa perubahan kardinal diperlukan di perpustakaan, maka ini tidak begitu sederhana dan, mungkin, ada baiknya untuk berpikir lagi dengan otak dan menggunakan perpustakaan ini dengan cara yang berbeda.
5 aturan emas
Saya mendapatkan aturan ini dalam praktik saya. Mereka tidak hanya menyangkut Python, tetapi juga bahasa lain di mana Anda dapat menggunakan ekstensi biner. Anda bisa berdebat dengan mereka, tetapi Anda juga bisa berpikir dan membawanya sendiri.
- Hanya fungsi ekspor . Membangun kelas dalam Python di perpustakaan biner cukup memakan waktu: Anda perlu menjelaskan banyak antarmuka, Anda perlu meninjau banyak integritas referensi dalam modul itu sendiri. Lebih mudah untuk menulis antarmuka kecil untuk fungsi tersebut.
- Gunakan kelas wrapper . Beberapa sangat menyukai OOP dan benar-benar menginginkan kelas. Bagaimanapun, bahkan jika ini bukan kelas, lebih baik menulis pembungkus Python: membuat kelas, mendefinisikan metode kelas atau metode biasa, panggil fungsi C / C ++ asli. Paling tidak, ini membantu menjaga integritas arsitektur data. Jika Anda menggunakan semacam C / C ++ ekstensi pihak ketiga yang tidak dapat Anda perbaiki, maka di bungkusnya Anda bisa meretasnya agar semuanya berfungsi.
- Anda tidak bisa meneruskan argumen dari Python ke ekstensi - ini bahkan bukan aturan, melainkan persyaratan. Dalam beberapa kasus, ini mungkin berhasil, tetapi biasanya ide yang buruk. Oleh karena itu, dalam kode Anda, Anda harus terlebih dahulu membuat handler yang menggunakan tipe Python untuk mengetik C. Dan hanya setelah itu memanggil fungsi asli apa pun yang sudah bekerja dengan tipe s. Handler yang sama menerima respons dari fungsi yang dapat dieksekusi dan mengubahnya menjadi tipe data Python, dan melemparkannya ke dalam kode Python.
- Mempertimbangkan pengumpulan sampah akun . Python memiliki GC yang terkenal, dan Anda tidak boleh melupakannya. Sebagai contoh, kami melewati sebagian besar teks dengan referensi dan mencoba menemukan beberapa kata di perpustakaan. Kami ingin memparalelkan ini, kami meneruskan tautan ke area memori ini dan ke peluncuran beberapa utas. Pada saat ini, GC hanya mengambil dan memutuskan bahwa tidak ada lagi yang mengacu pada objek ini dan memindahkannya dari area memori. Dalam kode yang sama, kami hanya mendapatkan referensi nol, dan ini biasanya kesalahan segmentasi. Kita tidak boleh melupakan fitur pengumpul sampah seperti itu dan meneruskan tipe data paling sederhana ke pustaka char: char, integer, dll.
Di sisi lain, bahasa tempat ekstensi ditulis mungkin memiliki pemulung sendiri. Kombinasi Python dan C # library adalah rasa sakit dalam pengertian ini.
- Secara eksplisit mendefinisikan argumen dari fungsi yang diekspor . Dengan ini, saya ingin mengatakan bahwa fungsi-fungsi ini perlu dijelaskan secara kualitatif. Jika kami menerima fungsi PyObject, dan dalam hal apa pun kami akan menerimanya di pustaka kami, maka kami perlu secara eksplisit menunjukkan argumen mana yang termasuk tipe yang mana. Ini berguna karena jika kita melewati tipe data yang salah, kita akan mendapatkan kesalahan di perpustakaan. Artinya, Anda membutuhkannya untuk kenyamanan Anda.
Arsitektur ekstensi biner

Sebenarnya, tidak ada yang rumit dalam arsitektur ekstensi biner. Ada Python, ada fungsi panggilan yang mendarat di bungkus yang secara asli memanggil kode. Panggilan ini pada gilirannya mendarat pada fungsi yang diekspor ke Python dan dapat langsung dipanggil. Dalam fungsi ini Anda perlu melemparkan tipe data ke tipe data bahasa Anda. Dan hanya setelah fungsi ini menerjemahkan semuanya kepada kami, kami memanggil fungsi asli, yang melakukan logika utama, mengembalikan hasilnya ke arah yang berlawanan dan melemparkannya ke Python, menerjemahkan kembali tipe data.
Teknologi dan Alat
Cara paling terkenal untuk menulis ekstensi biner adalah ekstensi Native C / C ++. Hanya karena itu adalah teknologi Python standar.
Ekstensi C / C ++ asli
Python sendiri diimplementasikan dalam C, dan metode dan struktur dari python.h digunakan untuk menulis ekstensi. Ngomong-ngomong, hal ini juga bagus karena sangat mudah untuk mengimplementasikannya dalam proyek yang sudah ada. Cukup menentukan xt_modules di setup.py dan mengatakan bahwa untuk membangun proyek Anda perlu mengkompilasi sumber-sumber tersebut dengan flag kompilasi seperti itu. Di bawah ini adalah contohnya.
name = 'DateTime.mxDateTime.mxDateTime' src = 'mxDateTime/mxDateTime.c' extra_compile_args=['-g3', '-o0', '-DDEBUG=2', '-UNDEBUG', '-std=c++11', '-Wall', '-Wextra'] setup ( ... ext_modules = [(name, { 'sources': [src], 'include_dirs': ['mxDateTime'] , extra_compile_args: extra_compile_args } )] )
Kelebihan dari Ekstensi C / C ++ Asli
- Teknologi asli.
- Mudah diintegrasikan ke dalam perakitan proyek.
- Jumlah dokumentasi terbesar.
- Memungkinkan Anda membuat tipe data Anda sendiri.
Kekurangan Native C / C ++ Extension
- Ambang entri tinggi.
- Pengetahuan tentang C. diperlukan
- Boost.Python.
- Kesalahan Segmentasi.
- Kesulitan dalam debugging.
Menurut teknologi ini, sejumlah besar dokumentasi ditulis, baik posting standar maupun blog. Nilai tambah yang besar adalah kita bisa melakukan tipe data Python kita sendiri dan membangun kelas kita.
Pendekatan ini memiliki kelemahan besar. Pertama, ini adalah ambang masuk - tidak semua orang tahu cukup C untuk membuat kode untuk produksi. Anda perlu memahami bahwa untuk ini tidak cukup membaca buku dan menjalankan untuk menulis ekstensi asli. Jika Anda ingin melakukan ini, maka: pertama, pelajari C; kemudian mulai menulis utilitas perintah; setelah itu baru lanjutkan menulis ekstensi.
Boost.Python sangat baik untuk C ++, memungkinkan Anda untuk hampir sepenuhnya abstrak dari semua pembungkus yang kami gunakan dalam Python. Tapi minusnya, saya pikir, adalah Anda perlu banyak berkeringat untuk mengambil sebagian dan mengimpornya ke dalam proyek tanpa mengunduh seluruh Boost.
Mendaftar kesulitan dalam debugging di minus, maksud saya sekarang semua orang terbiasa menggunakan debugger grafis, dan dengan modul biner hal seperti itu tidak akan berfungsi. Kemungkinan besar Anda perlu menginstal GDB dengan plugin untuk Python.
Mari kita lihat contoh bagaimana kita membuat ini.
#include <Python.h> static PyObject*addList_add(Pyobject* self, Pyobject* args){ PyObject * listObj; if (! PyARg_Parsetuple( args, "", &listObj)) return NULL; long length = PyList_Size(listObj) int i, sum =0; // return Py_BuildValue("i", sum); }
Untuk memulai, kami menyertakan file header Python. Setelah itu, kami menjelaskan fungsi addList_add yang akan digunakan Python. Yang paling penting adalah memberi nama fungsi dengan benar, dalam hal ini addList adalah nama modul, _add adalah nama fungsi yang akan digunakan dalam Python. Kami melewati modul PyObject itu sendiri dan meneruskan argumen menggunakan PyObject juga. Setelah itu, kami melakukan pemeriksaan standar. Dalam hal ini, kami mencoba menguraikan argumen tuple dan mengatakan bahwa itu adalah objek - literal "O" harus ditentukan secara eksplisit. Setelah itu, kita tahu bahwa kita melewatkan listObj sebagai objek, dan kami mencoba mencari tahu panjangnya menggunakan metode Python standar: PyList_Size. Catatan, di sini kita masih tidak dapat menggunakan panggilan panggilan untuk mengetahui panjang vektor ini, tetapi menggunakan fungsi Python. Kami mengabaikan implementasi, setelah itu perlu mengembalikan semua nilai kembali ke Python. Untuk melakukan ini, panggil Py_BuildValue, tentukan tipe data mana yang kami kembalikan, dalam hal ini "i" adalah bilangan bulat, dan jumlah variabel itu sendiri.
Dalam hal ini, semua orang mengerti - kami menemukan jumlah semua elemen dari daftar. Mari kita melangkah lebih jauh.
for(i = 0; i< length; i++){
Ini adalah hal yang sama, saat ini, listObj adalah objek Python. Dan dalam hal ini, kami mencoba untuk mengambil item daftar. Python.h memiliki semua yang Anda butuhkan untuk ini.
Setelah kami mendapatkan temp, kami mencoba untuk membuangnya terlalu lama. Dan hanya setelah itu Anda dapat melakukan sesuatu dalam C.
Setelah kami mengimplementasikan seluruh fungsi, kita perlu menulis dokumentasi.
Dokumentasi selalu baik , dan toolkit ini memiliki segalanya untuk perawatan yang mudah. Mengikuti konvensi penamaan, kami memberi nama modul addList_docs dan menyimpan deskripsi di sana. Sekarang Anda perlu mendaftar modul, untuk ini ada struktur PyMethodDef khusus. Menjelaskan properti, kita mengatakan bahwa fungsi diekspor ke Python dengan nama "add", yang fungsi ini memanggil PyCFunction. METH_VARARGS berarti bahwa suatu fungsi berpotensi mengambil sejumlah variabel. Kami juga menulis baris tambahan dan menjelaskan pemeriksaan standar, kalau-kalau kami hanya mengimpor modul, tetapi tidak menggunakan metode apa pun sehingga tidak jatuh.
Setelah kami mengumumkan semua ini, kami mencoba membuat modul. Kami membuat moduledef dan meletakkan semua yang kami lakukan di sana.
static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "addList example module", -1, adList_funcs, NULL, NULL, NULL, NULL };
PyModuleDef_HEAD_INIT adalah konstanta Python standar yang harus selalu Anda gunakan. -1 menunjukkan bahwa tidak ada memori tambahan yang perlu dialokasikan pada tahap impor.
Ketika kita membuat modul itu sendiri, kita perlu menginisialisasi itu. Python selalu mencari init, jadi buat PyInit_addList untuk addList. Sekarang dari struktur rakitan, Anda dapat memanggil PyModule_Create dan akhirnya membuat modul itu sendiri. Selanjutnya, tambahkan meta-informasi dan kembalikan modul itu sendiri.
PyInit_addList(void){ PyObject *module = PyModule_Create(&mdef); If (module == NULL) return NULL; PyModule_AddStringConstant(module, "__author__", "Bruse Lee<brus@kf.ch>:"); PyModule_addStringConstant (Module, "__version__", "1.0.0"); return module; }
Seperti yang telah Anda perhatikan, ada banyak hal yang harus diubah. Anda harus selalu ingat Python ketika kami menulis dalam C / C ++.
Itulah sebabnya, untuk memfasilitasi kehidupan seorang programmer fana biasa, sekitar 15 tahun yang lalu, teknologi SWIG muncul.
Meneguk
Alat ini memungkinkan Anda untuk mengambil abstrak dari binding Python dan menulis kode asli. Ini memiliki pro dan kontra yang sama dengan Native C / C ++, tetapi ada pengecualian.
SWIG Pro:
- Teknologi stabil.
- Sejumlah besar dokumentasi.
- Abstrak dari pengikatan ke Python.
Kekurangan SWIG:
- Pengaturan panjang.
- Pengetahuan C.
- Kesalahan Segmentasi.
- Kesulitan dalam debugging.
- Kompleksitas integrasi ke dalam perakitan proyek.
Kekurangan pertama adalah
saat Anda mengaturnya, Anda akan kehilangan akal . Ketika saya mengaturnya untuk pertama kalinya, saya menghabiskan satu setengah hari untuk meluncurkannya. Maka, tentu saja, lebih mudah. SWIG 3.x menjadi lebih mudah.
Agar tidak lagi masuk ke kode, pertimbangkan skema umum SWIG.

example.c adalah modul C yang tidak tahu apa-apa tentang Python sama sekali. Ada file antarmuka example.i, yang dijelaskan dalam format SWIG. Setelah itu, jalankan utilitas SWIG, yang membuat example_wrap.c dari file antarmuka - ini adalah pembungkus yang sama yang biasa kita lakukan dengan tangan kita. Artinya, SWIG hanya membuat pembungkus file untuk kita, yang disebut jembatan. Setelah itu, menggunakan GCC, kita mengkompilasi dua file dan mendapatkan dua file objek (example.o dan example_wrap.o) dan hanya dengan begitu kita membuat library kita. Semuanya sederhana dan jelas.
Cython
Andrey Svetlov membuat
laporan luar biasa di MoscowPython Conf, jadi saya hanya akan mengatakan bahwa ini adalah teknologi populer dengan dokumentasi yang baik.
Kelebihan Cython:
- Teknologi populer.
- Cukup stabil.
- Mudah diintegrasikan ke dalam perakitan proyek.
- Dokumentasi yang bagus.
Kekurangan dari Cython:
- Sintaksnya sendiri.
- Pengetahuan C.
- Kesalahan Segmentasi.
- Kesulitan dalam debugging.
Kontra, seperti biasa, adalah. Yang utama adalah sintaksnya sendiri, yang mirip dengan C / C ++, dan sangat mirip dengan Python.
Tetapi saya ingin menunjukkan bahwa kode Python dapat dipercepat menggunakan Cython dengan menulis kode asli.

Seperti yang Anda lihat, ada banyak dekorator, dan ini tidak terlalu bagus. Jika Anda ingin menggunakan Cython - lihat laporan Andrei Svetlov.
CTypes
CTypes adalah pustaka Python standar yang berfungsi dengan Antarmuka Fungsi Asing. FFI adalah perpustakaan tingkat rendah. Ini adalah teknologi asli, sangat sering digunakan dalam kode, dengan bantuannya mudah untuk mengimplementasikan lintas-platform.
Tapi FFI membawa banyak overhead karena semua jembatan, semua penangan saat runtime dibuat secara dinamis. Artinya, kami memuat pustaka dinamis, dan Python pada saat ini tidak tahu apa pustaka itu. Hanya ketika perpustakaan dipanggil dalam memori jembatan ini dibangun secara dinamis.
Kelebihan dari CTypes:
- Teknologi asli.
- Mudah digunakan dalam kode.
- Mudah untuk mengimplementasikan lintas-platform.
- Anda dapat menggunakan hampir semua bahasa.
CTypes Kontra:
- Membawa di atas kepala.
- Kesulitan dalam debugging.
from ctypes import *
Mereka mengambil adder.so dan menyebutnya runtime. Kita bahkan dapat mengirimkan tipe Python asli.
Setelah semua ini, pertanyaannya adalah: "Entah bagaimana rumit, di mana pun C, apa yang harus dilakukan?".
Karat
Pada suatu waktu, saya tidak memberikan perhatian yang tepat pada bahasa itu, tetapi sekarang saya praktis menoleh ke sana.
Kelebihan Karat:
- Bahasa yang aman.
- Jaminan statis yang kuat untuk perilaku yang benar.
- Mudah diintegrasikan ke dalam build proyek ( PyO3 ).
Kekurangan Karat:
- Ambang entri tinggi.
- Pengaturan panjang.
- Kesulitan dalam debugging.
- Ada sedikit dokumentasi.
- Dalam beberapa kasus, overhead.
Karat adalah bahasa yang aman dengan bukti kerja otomatis. Sintaksis itu sendiri dan preprocessor bahasa itu sendiri tidak memungkinkan kesalahan eksplisit dibuat. Pada saat yang sama, ini difokuskan pada variabilitas, yaitu, ia harus memproses setiap hasil dari eksekusi kode cabang.
Berkat tim PyO3, ada pengikat Python yang bagus untuk Rust, dan alat untuk diintegrasikan ke dalam proyek.
Pada sisi negatifnya, saya anggap itu untuk programmer yang tidak siap, butuh waktu yang sangat lama untuk mengkonfigurasinya. Beberapa dokumentasi, tetapi alih-alih kontra, kami tidak memiliki kesalahan segmentasi. Di Rust, dengan cara yang baik, dalam 99% kasus, seorang programmer bisa mendapatkan kesalahan segmentasi hanya jika ia secara eksplisit menunjukkan membuka dan hanya mencetaknya.
Contoh kecil kode, modul yang sama yang kami periksa sebelumnya.
#![feature(proc_macro)] #[macro_use] extern crate pyo3; Use pyo3::prelude::*;
Kode memiliki sintaksis tertentu, tetapi Anda terbiasa dengan sangat cepat. Faktanya, semuanya sama di sini. Menggunakan makro, kami membuat modinit, yang bagi kami melakukan semua pekerjaan tambahan untuk menghasilkan semua jenis pengikat untuk Python. Ingat saya katakan, Anda perlu melakukan handler wrapper, ini dia sama. run_py mengonversi jenis, maka kita memanggil kode asli.
Seperti yang Anda lihat, untuk mengekspor beberapa fungsi, ada gula sintaksis. Kami hanya mengatakan bahwa kami memerlukan fungsi add dan tidak menggambarkan antarmuka apa pun. Kami menerima daftar, yang persis py_list, bukan Object, karena Rust sendiri akan menyiapkan binder yang diperlukan pada saat kompilasi. Jika kami melewati tipe data yang salah, seperti dalam ekstensi ekstensi, TypeError akan terjadi. Setelah kami mendapatkan daftarnya, kami mulai memprosesnya.
Mari kita lihat lebih detail apa yang dia mulai lakukan.
#[pyfn(m, "add", py_list="*")] fn add(_py: Python, py_list: &PyList) -> PyResult<i32> { match py_list.len() { 0 =>Err(EmptyListError::new("List is empty")), _ => { let mut sum : i32 = 0; for item in py_list.iter() { let temp:i32 = match item.extract() { Ok(v) => v, Err(_) => { let err_msg: String = format!("List item {} is not int", item); return Err(ItemListError::new(err_msg)) } }; sum += temp; } Ok(sum) } } }
Kode yang sama yang ada di C / C ++ / Ctypes, tetapi hanya di Rust. Di sana saya mencoba untuk melemparkan PyObject ke beberapa jenis panjang. Apa yang akan terjadi jika kita mendaftar, kecuali angka, akankah kita mendapatkan string? Ya, kami akan mendapatkan SystemEerror. Dalam hal ini, melalui
let mut sum
: i32 = 0; kami juga mencoba untuk mendapatkan nilai dari daftar dan mengirimkannya ke i32. Artinya, kita tidak akan dapat menulis kode ini tanpa item.extract (), secara tidak sadar dan dilemparkan ke tipe yang diinginkan. Ketika kami menulis i32, dalam kasus kesalahan Rust, pada tahap kompilasi ia akan mengatakan: "Menangani kasus ketika bukan i32". Dalam hal ini, jika kita memiliki i32, kita mengembalikan nilai, jika ini adalah kesalahan, kita melempar pengecualian.
Apa yang harus dipilih
Setelah tur singkat ini, kami akan memikirkan apa yang harus dipilih pada akhirnya?
Jawabannya benar-benar sesuai dengan selera dan warna Anda.
Saya tidak akan mempromosikan teknologi spesifik apa pun.

Ringkas apa yang dikatakan:
- Dalam kasus SWIG dan C / C ++, Anda harus tahu C / C ++ dengan sangat baik, pahami bahwa pengembangan modul ini akan menimbulkan beberapa overhead tambahan. Tetapi minimum alat akan digunakan, dan kami akan bekerja dalam teknologi Python asli, yang didukung oleh pengembang.
- Dalam kasus Cython, kami memiliki ambang input kecil, kami memiliki kecepatan pengembangan tinggi, dan juga ini adalah generator kode biasa.
- Dengan mengorbankan CTypes, saya ingin memperingatkan Anda tentang overhead yang relatif besar. Pemuatan perpustakaan dinamis, ketika kita tidak tahu perpustakaan macam apa itu, dapat menyebabkan banyak masalah.
- Saya akan menyarankan Rust untuk membawa seseorang yang tidak tahu C / C ++ dengan baik. Karat dalam produksi benar-benar membawa masalah paling sedikit.
Panggilan untuk surat-surat
Kami menerima aplikasi untuk Moscow Python Conf ++ hingga 7 September - tulis dalam formulir sederhana ini yang Anda ketahui tentang Python yang benar-benar perlu Anda bagikan dengan komunitas.
Bagi mereka yang lebih tertarik mendengarkan, saya dapat berbicara tentang laporan keren.
- Donald Whyte suka berbicara tentang percepatan matematika dengan Python dan menyiapkan cerita baru untuk kita: bagaimana membuat matematika 10 kali lebih cepat menggunakan perpustakaan populer, trik dan kegelapan, dan kodenya dapat dimengerti dan didukung.
- Artyom Malyshev telah mengumpulkan semua pengalaman bertahun-tahun dalam mengembangkan Django dan mempresentasikan panduan laporan tentang kerangka kerja! Segala sesuatu yang terjadi antara menerima permintaan HTTP dan mengirim halaman web yang sudah selesai: mengekspos sihir, peta mekanisme internal kerangka kerja, dan banyak tips berguna untuk proyek Anda.