Membungkus pustaka C dengan Python: C, Cython atau ctypes?

284

Saya ingin memanggil perpustakaan C dari aplikasi Python. Saya tidak ingin membungkus seluruh API, hanya fungsi dan tipe data yang relevan dengan kasus saya. Seperti yang saya lihat, saya punya tiga pilihan:

  1. Buat modul ekstensi aktual dalam C. Mungkin berlebihan, dan saya juga ingin menghindari overhead belajar menulis ekstensi.
  2. Gunakan Cython untuk mengekspos bagian yang relevan dari pustaka C ke Python.
  3. Lakukan semuanya dengan Python, gunakan ctypesuntuk berkomunikasi dengan perpustakaan eksternal.

Saya tidak yakin apakah 2) atau 3) adalah pilihan yang lebih baik. Keuntungan dari 3) adalah ituctypes adalah bagian dari perpustakaan standar, dan kode yang dihasilkan akan menjadi Python murni - walaupun saya tidak yakin seberapa besar sebenarnya keuntungan itu.

Apakah ada lebih banyak keuntungan / kerugian dengan salah satu pilihan? Pendekatan mana yang Anda rekomendasikan?


Sunting: Terima kasih atas semua jawaban Anda, mereka menyediakan sumber yang bagus untuk siapa pun yang ingin melakukan sesuatu yang serupa. Keputusan, tentu saja, masih harus dibuat untuk satu kasus — tidak ada jawaban "Ini adalah hal yang benar". Untuk kasus saya sendiri, saya mungkin akan menggunakan ctypes, tapi saya juga berharap untuk mencoba Cython di beberapa proyek lain.

Dengan tidak adanya jawaban yang benar, menerima jawaban agak sewenang-wenang; Saya memilih jawaban FogleBird karena memberikan beberapa wawasan yang baik tentang ctypes dan saat ini juga merupakan jawaban dengan suara tertinggi. Namun, saya sarankan untuk membaca semua jawaban untuk mendapatkan gambaran yang bagus.

Terima kasih lagi.

balpha
sumber
3
Hingga taraf tertentu, aplikasi spesifik yang terlibat (apa yang dilakukan perpustakaan) dapat memengaruhi pilihan pendekatan. Kami telah menggunakan ctypes cukup berhasil untuk berbicara dengan DLL yang disediakan vendor untuk berbagai potongan hardare (misalnya osiloskop) tetapi saya tidak perlu memilih ctypes pertama untuk berbicara dengan perpustakaan pemrosesan numerik, karena overhead tambahan dibandingkan dengan Cython atau SWIG.
Peter Hansen
1
Sekarang Anda memiliki apa yang Anda cari. Empat jawaban berbeda. (Seseorang juga menemukan SWIG). Itu berarti bahwa sekarang Anda memiliki 4 pilihan, bukan 3.
Luka Rahne
@ralu Itulah yang saya duga, juga :-) Tapi serius, saya tidak mengharapkan (atau menginginkan) tabel pro / kontra atau satu jawaban tunggal yang mengatakan "Inilah yang perlu Anda lakukan". Setiap pertanyaan tentang pengambilan keputusan dijawab dengan baik dengan "penggemar" dari setiap pilihan yang mungkin memberikan alasan mereka. Pemungutan suara komunitas kemudian melakukan bagiannya, seperti halnya pekerjaan saya sendiri (melihat argumen, menerapkannya pada kasus saya, membaca sumber yang disediakan, dll). Singkat cerita: Ada beberapa jawaban bagus di sini.
balpha
Jadi, pendekatan mana yang akan Anda gunakan? :)
FogleBird
1
Sejauh yang saya tahu (tolong perbaiki saya jika saya salah), Cython adalah fork dari Pyrex dengan pengembangan lebih lanjut ke dalamnya, membuat Pyrex cukup usang.
balpha

Jawaban:

115

ctypes adalah taruhan terbaik Anda untuk menyelesaikannya dengan cepat, dan itu menyenangkan untuk dikerjakan karena Anda masih menulis Python!

Saya baru-baru ini membungkus FTDI driver untuk berkomunikasi dengan chip USB menggunakan ctypes dan itu hebat. Saya telah menyelesaikan semuanya dan bekerja dalam waktu kurang dari satu hari kerja. (Saya hanya mengimplementasikan fungsi yang kami butuhkan, sekitar 15 fungsi).

Kami sebelumnya menggunakan modul pihak ketiga, PyUSB , untuk tujuan yang sama. PyUSB adalah modul ekstensi C / Python yang sebenarnya. Tapi PyUSB tidak melepaskan GIL saat melakukan pemblokiran baca / tulis, yang menyebabkan masalah bagi kami. Jadi saya menulis modul kami sendiri menggunakan ctypes, yang memang melepaskan GIL saat memanggil fungsi asli.

Satu hal yang perlu diperhatikan adalah bahwa ctypes tidak akan tahu #define konstanta dan hal-hal di perpustakaan yang Anda gunakan, hanya fungsinya, jadi Anda harus mendefinisikan ulang konstanta-konstanta tersebut dalam kode Anda sendiri.

Berikut ini adalah contoh bagaimana kode tersebut terlihat (banyak yang diambil, hanya mencoba menunjukkan intinya):

from ctypes import *

d2xx = WinDLL('ftd2xx')

OK = 0
INVALID_HANDLE = 1
DEVICE_NOT_FOUND = 2
DEVICE_NOT_OPENED = 3

...

def openEx(serial):
    serial = create_string_buffer(serial)
    handle = c_int()
    if d2xx.FT_OpenEx(serial, OPEN_BY_SERIAL_NUMBER, byref(handle)) == OK:
        return Handle(handle.value)
    raise D2XXException

class Handle(object):
    def __init__(self, handle):
        self.handle = handle
    ...
    def read(self, bytes):
        buffer = create_string_buffer(bytes)
        count = c_int()
        if d2xx.FT_Read(self.handle, buffer, bytes, byref(count)) == OK:
            return buffer.raw[:count.value]
        raise D2XXException
    def write(self, data):
        buffer = create_string_buffer(data)
        count = c_int()
        bytes = len(data)
        if d2xx.FT_Write(self.handle, buffer, bytes, byref(count)) == OK:
            return count.value
        raise D2XXException

Seseorang melakukan beberapa tolok ukur pada berbagai opsi.

Saya mungkin lebih ragu-ragu jika saya harus membungkus pustaka C ++ dengan banyak kelas / template / dll. Tapi ctypes bekerja dengan baik dengan struct dan bahkan dapat dipanggil kembali ke Python.

FogleBird
sumber
5
Bergabung dengan pujian untuk ctypes, tetapi perhatikan satu (tidak terdokumentasi) masalah: ctypes tidak mendukung forking. Jika Anda memotong dari proses menggunakan ctypes, dan kedua proses induk dan anak terus menggunakan ctypes, Anda akan menemukan bug jahat yang ada hubungannya dengan ctypes menggunakan memori bersama.
Oren Shemesh
1
@ OrenShemesh Apakah ada bacaan lebih lanjut tentang masalah ini yang bisa Anda tunjukkan? Saya pikir saya mungkin aman dengan proyek yang sedang saya kerjakan, karena saya percaya hanya proses induk yang menggunakan ctypes(untuk pyinotify), tetapi saya ingin memahami masalahnya lebih menyeluruh.
zigg
Bagian ini banyak membantu saya One thing to note is that ctypes won't know about #define constants and stuff in the library you're using, only the functions, so you'll have to redefine those constants in your own code.Jadi, saya harus mendefinisikan konstanta yang ada di winioctl.h....
swdev
bagaimana dengan kinerja? ctypesjauh lebih lambat daripada ekstensi-c karena bottleneck adalah antarmuka dari Python ke C
TomSawyer
154

Peringatan: pendapat pengembang inti Cython di depan.

Saya hampir selalu merekomendasikan Cython di atas ctypes. Alasannya adalah karena memiliki jalur peningkatan yang jauh lebih lancar. Jika Anda menggunakan ctypes, banyak hal akan menjadi sederhana pada awalnya, dan tentu saja keren untuk menulis kode FFI Anda dengan Python polos, tanpa kompilasi, membangun dependensi dan sebagainya. Namun, pada titik tertentu, Anda hampir pasti akan menemukan bahwa Anda harus sering menelepon ke perpustakaan C Anda, baik dalam satu lingkaran atau dalam serangkaian panggilan yang saling tergantung yang lebih lama, dan Anda ingin mempercepatnya. Itulah titik di mana Anda akan melihat bahwa Anda tidak dapat melakukannya dengan ctypes. Atau, ketika Anda membutuhkan fungsi panggilan balik dan Anda menemukan bahwa kode panggilan balik Python Anda menjadi hambatan, Anda ingin mempercepatnya dan / atau memindahkannya ke C juga. Sekali lagi, Anda tidak bisa melakukannya dengan ctypes.

Dengan Cython, OTOH, Anda benar-benar bebas untuk membuat kode pembungkus dan panggilan setipis atau setebal yang Anda inginkan. Anda dapat mulai dengan panggilan sederhana ke dalam kode C dari kode Python biasa, dan Cython akan menerjemahkannya ke dalam panggilan C asli, tanpa overhead panggilan tambahan, dan dengan overhead konversi yang sangat rendah untuk parameter Python. Ketika Anda menyadari bahwa Anda memerlukan kinerja yang lebih besar di beberapa titik di mana Anda membuat terlalu banyak panggilan mahal ke pustaka C Anda, Anda bisa mulai membuat anotasi kode Python di sekitarnya dengan tipe statis dan membiarkan Cython mengoptimalkannya langsung ke C untuk Anda. Atau, Anda dapat mulai menulis ulang bagian kode C Anda di Cython untuk menghindari panggilan dan untuk mengkhususkan dan mengencangkan loop Anda secara algoritmik. Dan jika Anda membutuhkan panggilan cepat, cukup tulis fungsi dengan tanda tangan yang sesuai dan berikan langsung ke registri panggilan balik C secara langsung. Sekali lagi, tidak ada overhead, dan itu memberi Anda kinerja panggilan C sederhana. Dan dalam kasus yang jauh lebih kecil kemungkinannya bahwa Anda benar-benar tidak bisa mendapatkan kode Anda cukup cepat di Cython, Anda masih dapat mempertimbangkan untuk menulis ulang bagian yang benar-benar kritis dalam C (atau C ++ atau Fortran) dan menyebutnya dari kode Cython Anda secara alami dan asli. Tapi kemudian, ini benar-benar menjadi pilihan terakhir alih-alih satu-satunya pilihan.

Jadi, ctypes senang melakukan hal-hal sederhana dan dengan cepat menjalankan sesuatu. Namun, begitu hal mulai tumbuh, Anda kemungkinan besar akan sampai pada titik di mana Anda melihat bahwa Anda sebaiknya menggunakan Cython sejak awal.

Stefan Behnel
sumber
4
+1 itu poin bagus, terima kasih banyak! Meskipun saya bertanya-tanya apakah hanya memindahkan bagian bottleneck ke Cython benar-benar sebesar ini. Tapi saya setuju, jika Anda mengharapkan masalah kinerja apa pun, Anda sebaiknya menggunakan Cython dari awal.
balpha
Apakah ini masih berlaku untuk programmer yang berpengalaman dengan C dan Python? Dalam hal ini orang mungkin berpendapat bahwa Python / ctypes adalah pilihan yang lebih baik, karena vektorisasi C loop (SIMD) kadang-kadang lebih mudah. Tapi, selain itu, saya tidak bisa memikirkan kelemahan Cython.
Alex van Houten
Terima kasih atas jawabannya! Satu hal yang saya punya masalah dengan Cython adalah mendapatkan proses pembuatan yang benar (tapi itu juga ada hubungannya dengan saya tidak pernah menulis modul Python sebelumnya) - harus saya kompilasi sebelumnya, atau sertakan file sumber Cython dalam sdist dan pertanyaan serupa. Saya menulis posting blog tentang itu kalau-kalau ada yang memiliki masalah / keraguan yang sama: martinsosic.com/development/2016/02/08/…
Martinsos
Terima kasih atas jawabannya! Satu kekurangan ketika saya menggunakan Cython adalah bahwa operator overloading tidak sepenuhnya diimplementasikan (misalnya __radd__). Ini sangat menjengkelkan ketika Anda berencana untuk kelas Anda untuk berinteraksi dengan tipe builtin (misalnya intdan float). Juga, metode ajaib dalam cython hanya sedikit buggy secara umum.
Monolith
100

Cython adalah alat yang cukup keren, layak untuk dipelajari, dan secara mengejutkan dekat dengan sintaks Python. Jika Anda melakukan komputasi ilmiah apa pun dengan Numpy, maka Cython adalah cara yang harus dilakukan karena terintegrasi dengan Numpy untuk operasi matriks cepat.

Cython adalah superset dari bahasa Python. Anda dapat membuang file Python yang valid padanya, dan itu akan memuntahkan program C yang valid. Dalam hal ini, Cython hanya akan memetakan panggilan Python ke API CPython yang mendasarinya. Ini mungkin menghasilkan speedup 50% karena kode Anda tidak lagi ditafsirkan.

Untuk mendapatkan beberapa optimasi, Anda harus mulai memberi tahu Cython fakta tambahan tentang kode Anda, seperti ketik deklarasi. Jika Anda cukup mengatakannya, itu bisa mendidih kode ke murni C. Artinya, untuk loop di Python menjadi untuk loop di C. Di sini Anda akan melihat peningkatan kecepatan besar-besaran. Anda juga dapat menautkan ke program C eksternal di sini.

Menggunakan kode Cython juga sangat mudah. Saya pikir manual membuatnya terdengar sulit. Anda benar-benar hanya melakukan:

$ cython mymodule.pyx
$ gcc [some arguments here] mymodule.c -o mymodule.so

dan kemudian Anda bisa import mymoduledalam kode Python Anda dan lupa sepenuhnya bahwa itu dikompilasi ke C.

Bagaimanapun, karena Cython sangat mudah untuk diatur dan mulai digunakan, saya sarankan mencoba untuk melihat apakah itu sesuai dengan kebutuhan Anda. Ini tidak akan sia-sia jika ternyata tidak menjadi alat yang Anda cari.

carl
sumber
1
Tidak masalah. Yang menyenangkan tentang Cython adalah Anda hanya bisa belajar apa yang Anda butuhkan. Jika Anda hanya menginginkan peningkatan sederhana, yang harus Anda lakukan adalah mengkompilasi file Python Anda dan selesai.
carl
18
"Anda dapat membuang file Python yang valid padanya, dan itu akan memunculkan program C yang valid." <- Tidak juga, ada beberapa batasan: docs.cython.org/src/userguide/limitations.html Mungkin bukan masalah untuk sebagian besar kasus penggunaan, tetapi hanya ingin lengkap.
Randy Syring
7
Masalah semakin berkurang dengan setiap rilis, ke titik bahwa halaman itu sekarang mengatakan "sebagian besar masalah telah diselesaikan pada 0,15".
Henry Gomersall
3
Untuk menambahkan, ada BAHKAN cara yang lebih mudah untuk mengimpor kode cython: tulis kode cython Anda sebagai mymod.pyxmodul dan kemudian lakukan import pyximport; pyximport.install(); import mymoddan kompilasi terjadi di belakang layar.
Kaushik Ghose
3
@kaushik Lebih sederhana adalah pypi.python.org/pypi/runcython . Gunakan saja runcython mymodule.pyx. Dan tidak seperti pyximport, Anda dapat menggunakannya untuk tugas penautan yang lebih banyak. Satu-satunya peringatan adalah bahwa akulah yang menulis 20 baris bash untuk itu dan mungkin bias.
RussellStewart
42

Untuk memanggil pustaka C dari aplikasi Python ada juga cffi yang merupakan alternatif baru untuk ctypes . Ini membawa tampilan baru untuk FFI:

  • ini menangani masalah dengan cara yang menarik dan bersih (tidak seperti ctypes )
  • tidak perlu menulis kode Python (seperti dalam SWIG, Cython , ...)
Robert Zaremba
sumber
pasti cara untuk pembungkus , seperti yang diinginkan OP. cython terdengar bagus untuk menulis mereka loop panas sendiri, tetapi untuk antarmuka, cffi hanya merupakan peningkatan langsung dari ctypes.
domba terbang
21

Saya akan melemparkan yang lain di luar sana: SWIG

Mudah dipelajari, melakukan banyak hal dengan benar, dan mendukung lebih banyak bahasa sehingga waktu yang dihabiskan untuk mempelajarinya bisa sangat berguna.

Jika Anda menggunakan SWIG, Anda membuat modul ekstensi python baru, tetapi dengan SWIG melakukan sebagian besar tugas berat untuk Anda.

Chris Arguin
sumber
18

Secara pribadi, saya akan menulis modul ekstensi dalam C. Jangan terintimidasi oleh ekstensi Python C - mereka tidak sulit sama sekali untuk menulis. Dokumentasinya sangat jelas dan bermanfaat. Ketika saya pertama kali menulis ekstensi C dengan Python, saya pikir butuh sekitar satu jam untuk mencari cara menulis satu - tidak banyak waktu sama sekali.

mipadi
sumber
Membungkus perpustakaan C. Anda sebenarnya dapat menemukan kode di sini: github.com/mdippery/lehmer
mipadi
1
@ forivall: Kode tidak terlalu berguna, dan ada generator nomor acak yang lebih baik di luar sana. Saya hanya punya cadangan di komputer saya.
mipadi
2
Sepakat. Python C-API hampir tidak menakutkan seperti yang terlihat (dengan asumsi Anda tahu C). Namun, tidak seperti dengan python dan cadangan pustaka, sumber daya, dan pengembangnya, saat menulis ekstensi di C pada dasarnya Anda sendirian. Mungkin satu-satunya kelemahan (selain dari yang biasanya datang dengan menulis dalam C).
Noob Saibot
1
@mipadi: well, tetapi mereka berbeda antara Python 2.x dan 3.x, jadi lebih mudah menggunakan Cython untuk menulis ekstensi Anda, minta Cython mencari tahu semua perinciannya dan kemudian kompilasi kode C yang dihasilkan untuk Python 2.x atau 3.x sesuai kebutuhan.
0xC0000022L
2
@mipadi sepertinya tautan github sudah mati dan sepertinya tidak tersedia di archive.org, apakah Anda memiliki cadangan?
jrh
11

ctypes sangat bagus ketika Anda sudah punya gumpalan perpustakaan dikompilasi untuk berurusan dengan (seperti perpustakaan OS). Namun, overhead panggilan sangat parah, jadi jika Anda akan membuat banyak panggilan ke perpustakaan, dan Anda akan tetap menulis kode C (atau setidaknya mengkompilasinya), saya akan mengatakan untuk cython . Ini bukan pekerjaan yang lebih, dan akan jauh lebih cepat dan lebih pythonic untuk menggunakan file pyd yang dihasilkan.

Saya pribadi cenderung menggunakan cython untuk mempercepat kode python (loop dan perbandingan integer adalah dua area di mana cython sangat bersinar), dan ketika ada beberapa kode yang lebih terlibat / pembungkus perpustakaan lain yang terlibat, saya akan beralih ke Boost.Python . Boost.Python bisa jadi rumit untuk diatur, tetapi begitu Anda berhasil, itu membuat membungkus kode C / C ++ secara langsung.

cython juga hebat dalam membungkus numpy (yang saya pelajari dari proses SciPy 2009 ), tapi saya belum pernah menggunakan numpy, jadi saya tidak bisa mengomentari itu.

Ryan Ginstrom
sumber
11

Jika Anda sudah memiliki perpustakaan dengan API yang ditentukan, saya pikir ctypesadalah pilihan terbaik, karena Anda hanya perlu melakukan sedikit inisialisasi dan kemudian memanggil perpustakaan dengan cara yang biasa Anda lakukan.

Saya pikir Cython atau membuat modul ekstensi dalam C (yang tidak terlalu sulit) lebih berguna ketika Anda membutuhkan kode baru, misalnya memanggil perpustakaan itu dan melakukan beberapa tugas yang kompleks, memakan waktu, dan kemudian meneruskan hasilnya ke Python.

Pendekatan lain, untuk program sederhana, secara langsung melakukan proses yang berbeda (dikompilasi secara eksternal), mengeluarkan hasilnya ke output standar dan menyebutnya dengan modul subproses. Terkadang itu pendekatan yang paling mudah.

Misalnya, jika Anda membuat program konsol C yang berfungsi kurang lebih seperti itu

$miCcode 10
Result: 12345678

Anda bisa menyebutnya dari Python

>>> import subprocess
>>> p = subprocess.Popen(['miCcode', '10'], shell=True, stdout=subprocess.PIPE)
>>> std_out, std_err = p.communicate()
>>> print std_out
Result: 12345678

Dengan sedikit memformat string, Anda dapat mengambil hasilnya dengan cara apa pun yang Anda inginkan. Anda juga dapat menangkap output kesalahan standar, sehingga cukup fleksibel.

Khelben
sumber
Meskipun tidak ada yang salah dengan jawaban ini, orang-orang harus berhati-hati jika kode tersebut dibuka untuk diakses oleh orang lain karena memanggil subproses dengan shell=Truedapat dengan mudah mengakibatkan semacam eksploitasi ketika pengguna benar-benar mendapatkan shell. Tidak apa-apa ketika pengembang adalah satu-satunya pengguna, tetapi di dunia ada banyak tusukan menjengkelkan hanya menunggu sesuatu seperti ini.
Ben
7

Ada satu masalah yang membuat saya menggunakan ctypes dan bukan cython dan yang tidak disebutkan dalam jawaban lain.

Menggunakan ctypes hasilnya tidak tergantung pada kompiler yang Anda gunakan sama sekali. Anda dapat menulis perpustakaan menggunakan kurang lebih bahasa apa pun yang dapat dikompilasi ke perpustakaan bersama asli. Tidak masalah, sistem mana, bahasa mana dan kompiler mana. Cython, bagaimanapun, dibatasi oleh infrastruktur. Misalnya, jika Anda ingin menggunakan intel compiler di windows, jauh lebih sulit untuk membuat cython berfungsi: Anda harus "menjelaskan" kompiler ke cython, mengkompilasi ulang sesuatu dengan kompiler yang tepat ini, dll. Yang secara signifikan membatasi portabilitas.

Misha
sumber
4

Jika Anda menargetkan Windows dan memilih untuk membungkus beberapa pustaka C ++ yang dipatenkan, maka Anda mungkin segera menemukan bahwa versi yang berbeda dari msvcrt***.dll(Visual C ++ Runtime) sedikit tidak kompatibel.

Ini berarti bahwa Anda mungkin tidak dapat menggunakan Cythonkarena hasilnya wrapper.pydditautkan dengan msvcr90.dll (Python 2.7) atau msvcr100.dll (Python 3.x) . Jika pustaka yang Anda bungkus terkait dengan versi runtime yang berbeda, maka Anda kurang beruntung.

Kemudian untuk membuat semuanya berfungsi, Anda harus membuat pembungkus C untuk pustaka C ++, tautan dll pembungkus itu dengan versi yang sama msvcrt***.dllseperti pustaka C ++ Anda. Dan kemudian gunakan ctypesuntuk memuat dll pembungkus linting tangan Anda secara dinamis saat runtime.

Jadi ada banyak detail kecil, yang dijelaskan dengan sangat rinci dalam artikel berikut:

"Perpustakaan Asli yang Indah (dengan Python) ": http://lucumr.pocoo.org/2013/8/18/beautiful-native-libraries/

iljau
sumber
Artikel itu tidak ada hubungannya dengan masalah yang Anda bawa dengan kompatibilitas kompiler Microsoft. Mendapatkan ekstensi Cython bekerja di Windows sebenarnya tidak terlalu sulit. Saya sudah bisa menggunakan MinGW untuk hampir semua hal. Distribusi Python yang baik membantu.
IanH
2
+1 untuk menyebutkan kemungkinan masalah pada windows (yang saat ini saya alami juga ...). @ IanH itu kurang tentang windows secara umum, tapi berantakan jika Anda terjebak dengan lib pihak ketiga yang diberikan yang tidak cocok dengan distribusi python Anda.
sebastian
2

Saya tahu ini adalah pertanyaan lama tetapi hal ini muncul di google ketika Anda mencari hal-hal seperti ctypes vs cython, dan sebagian besar jawaban di sini ditulis oleh mereka yang sudah mahir cythonatau cyang mungkin tidak mencerminkan waktu sebenarnya yang Anda butuhkan untuk berinvestasi untuk mempelajari hal itu untuk mengimplementasikan solusi Anda. Saya seorang pemula yang lengkap dalam keduanya. Saya belum pernah menyentuh cythonsebelumnya, dan memiliki sedikit pengalaman c/c++.

Selama dua hari terakhir, saya sedang mencari cara untuk mendelegasikan kinerja bagian yang berat dari kode saya ke sesuatu yang lebih rendah daripada python. Saya menerapkan kode saya di ctypesdan Cython, yang pada dasarnya terdiri dari dua fungsi sederhana.

Saya punya daftar string besar yang perlu diproses. Perhatikan listdan string. Kedua tipe tidak cocok dengan tipe di c, karena string python secara default unicode dan cstring tidak. Daftar dalam python BUKAN array dari c.

Inilah vonis saya. Gunakan cython. Ini terintegrasi lebih lancar ke python, dan lebih mudah untuk dikerjakan secara umum. Ketika terjadi kesalahan ctypeshanya membuat Anda segfault, setidaknya cythonakan memberi Anda kompilasi peringatan dengan jejak tumpukan kapan pun memungkinkan, dan Anda dapat mengembalikan objek python yang valid dengan mudah cython.

Berikut ini adalah akun terperinci tentang berapa banyak waktu yang saya perlukan untuk berinvestasi di keduanya untuk mengimplementasikan fungsi yang sama. Saya melakukan sangat sedikit pemrograman C / C ++:

  • Ctypes:

    • Tentang 2h tentang meneliti bagaimana mengubah daftar string unicode saya menjadi tipe yang kompatibel.
    • Sekitar satu jam tentang cara mengembalikan string dengan benar dari fungsi ac. Di sini saya benar-benar memberikan solusi saya sendiri untuk SO begitu saya telah menulis fungsinya.
    • Sekitar setengah jam untuk menulis kode dalam c, kompilasi ke perpustakaan dinamis.
    • 10 menit untuk menulis kode uji dalam python untuk memeriksa apakah ckode itu berfungsi.
    • Sekitar satu jam melakukan beberapa tes dan menyusun ulang ckode.
    • Kemudian saya menancapkan ckode ke basis kode yang sebenarnya, dan melihat bahwa ctypestidak cocok dengan multiprocessingmodul karena handlernya tidak dapat dipilih secara default.
    • Sekitar 20 menit saya mengatur ulang kode saya untuk tidak menggunakan multiprocessingmodul, dan coba lagi.
    • Kemudian fungsi kedua dalam ckode saya menghasilkan segfault di basis kode saya meskipun melewati kode pengujian saya. Yah, ini mungkin salah saya karena tidak memeriksa dengan baik dengan kasus tepi, saya mencari solusi cepat.
    • Selama sekitar 40 menit saya mencoba menentukan kemungkinan penyebab segfault ini.
    • Saya membagi fungsi saya menjadi dua perpustakaan dan mencoba lagi. Masih memiliki segfaults untuk fungsi kedua saya.
    • Saya memutuskan untuk melepaskan fungsi kedua dan hanya menggunakan fungsi pertama dari ckode dan pada iterasi kedua atau ketiga dari loop python yang menggunakannya, saya punya UnicodeErrortentang tidak men-decoding byte pada beberapa posisi meskipun saya menyandikan dan mendekodekan everthing secara eksplisit.

Pada titik ini, saya memutuskan untuk mencari alternatif dan memutuskan untuk mencari cython:

  • Cython
    • 10 mnt membaca cython hello world .
    • 15 menit memeriksa SO tentang cara menggunakan cython dengan setuptoolsalih - alih distutils.
    • 10 menit membaca tentang tipe cython dan tipe python. Saya belajar saya bisa menggunakan sebagian besar tipe python builtin untuk mengetik statis.
    • 15 mnt untuk mengatur ulang kode python saya dengan tipe cython.
    • 10 menit memodifikasi saya setup.pyuntuk menggunakan modul yang dikompilasi dalam basis kode saya.
    • Dicolokkan dalam modul langsung ke multiprocessingversi basis kode. Berhasil.

Sebagai catatan, tentu saja saya tidak mengukur waktu yang tepat untuk investasi saya. Mungkin benar bahwa persepsi saya tentang waktu sedikit untuk diperhatikan karena upaya mental yang diperlukan ketika saya berurusan dengan ctypes. Tetapi harus menyampaikan perasaan berurusan dengan cythondanctypes

Kaan E.
sumber