Ottimizza il tuo codice Python con C
Cython crea moduli C che accelerano l'esecuzione del codice Python, importante per applicazioni complesse in cui un linguaggio interpretato non è efficiente.
Cython è un compilatore per il linguaggio di programmazione Python pensato per ottimizzare le prestazioni e formare un linguaggio di programmazione Cython esteso. Come estensione di Python, Cython è anche un superset del linguaggio Python e supporta la chiamata di funzioni C e la dichiarazione di tipi C su variabili e attributi di classe. Ciò semplifica il confezionamento di librerie C esterne, l'incorporamento di C in applicazioni esistenti o la scrittura di estensioni C per Python con una sintassi semplice come quella di Python stesso.
Cython è comunemente usato per creare moduli C che accelerano l'esecuzione del codice Python. Ciò è importante in applicazioni complesse in cui un linguaggio interpretato non è efficiente.
Installa Cython
Puoi installare Cython su Linux, BSD, Windows o macOS utilizzando Python:
$ python -m pip install Cython
Una volta installato, è pronto per l'uso.
Trasforma Python in C
Un buon modo per iniziare con Cython è con una semplice applicazione "ciao mondo". Non è la migliore dimostrazione dei vantaggi di Cython, ma mostra cosa succede quando usi Cython.
Innanzitutto, crea questo semplice script Python in un file chiamato hello.pyx
(l'estensione .pyx
non è magica e tecnicamente potrebbe essere qualsiasi cosa, ma è l'estensione predefinita di Cython) :
print("hello world")
Successivamente, crea uno script di installazione Python. Un file setup.py
è come la versione Python di un makefile e Cython può usarlo per elaborare il tuo codice Python:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("hello.pyx")
)
Infine, usa Cython per trasformare il tuo script Python in codice C:
$ python setup.py build_ext --inplace
Puoi vedere i risultati nella directory del tuo progetto. Il modulo cythonize
di Cython trasforma hello.pyx
in un file hello.c
e una libreria .so
. Il codice C è di 2.648 righe, quindi è molto più testo della singola riga del sorgente hello.pyx
. La libreria .so
è inoltre oltre 2.000 volte più grande della sua sorgente (54.000 rispetto a 20 byte). Inoltre, Python è necessario per eseguire un singolo script Python, quindi c'è molto codice che sostiene quel file hello.pyx
a riga singola.
Per utilizzare la versione in codice C del tuo script Python "hello world", apri un prompt Python e importa il nuovo modulo hello
che hai creato:
>>> import hello
hello world
Integra il codice C in Python
Un buon test generico della potenza di calcolo è il calcolo dei numeri primi. Un numero primo è un numero positivo maggiore di 1 che produce un intero positivo solo se diviso per 1 o per se stesso. In teoria è semplice, ma man mano che i numeri aumentano, aumentano anche i requisiti di calcolo. In Python puro, può essere fatto in meno di 10 righe di codice:
import sys
number = int(sys.argv[1])
if not number <= 1:
for i in range(2, number):
if (number % i) == 0:
print("Not prime")
break
else:
print("Integer must be greater than 1")
Questo script tace in caso di successo e restituisce un messaggio se il numero non è primo:
$ ./prime.py 3
$ ./prime.py 4
Not prime.
Convertirlo in Cython richiede un po' di lavoro, in parte per rendere il codice appropriato per l'uso come libreria e in parte per le prestazioni.
Script e librerie
Molti utenti imparano Python come linguaggio di scripting: dici a Python i passaggi che vuoi che esegua e lui fa il lavoro. Man mano che impari di più su Python (e sulla programmazione open source in generale), impari che gran parte del codice più potente disponibile si trova nelle librerie che altre applicazioni possono sfruttare. Quanto più meno specifico è il tuo codice, tanto più è probabile che possa essere riproposto da un programmatore (incluso tu) per altre applicazioni. Può richiedere un po' più di lavoro separare il calcolo dal flusso di lavoro, ma alla fine, di solito, ne vale la pena.
Nel caso di questo semplice calcolatore di numeri primi, la conversione in Cython inizia con uno script di installazione:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("prime.py")
)
Trasforma il tuo script in C:
$ python setup.py build_ext --inplace
Finora sembra che tutto funzioni bene, ma quando tenti di importare e utilizzare il nuovo modulo, ricevi un errore:
>>> import prime
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "prime.py", line 2, in init prime
number = sys.argv[1]
IndexError: list index out of range
Il problema è che uno script Python si aspetta di essere eseguito da un terminale, dove gli argomenti (in questo caso, un numero intero da testare come numero primo) sono comuni. È necessario modificare lo script in modo che possa essere utilizzato come libreria.
Scrivi una biblioteca
Le librerie non utilizzano argomenti di sistema e accettano invece argomenti da altro codice. Invece di usare sys.argv
per inserire l'input dell'utente, rendi il tuo codice una funzione che accetta un argomento chiamato number
(o num
o qualsiasi altra variabile nome che preferisci):
def calculate(number):
if not number <= 1:
for i in range(2, number):
if (number % i) == 0:
print("Not prime")
break
else:
print("Integer must be greater than 1")
Ciò rende certamente il tuo script un po' difficile da testare perché quando esegui il codice in Python, la funzione calculate
non viene mai eseguita. Tuttavia, i programmatori Python hanno escogitato una soluzione comune, se non intuitiva, per questo problema. Quando l'interprete Python esegue uno script Python, c'è una variabile speciale chiamata __name__
che viene impostata su __main__
, ma quando viene importata come modulo, __name__
è impostato sul nome del modulo. Sfruttando questo, puoi scrivere una libreria che sia sia un modulo Python che uno script Python valido:
import sys
def calculate(number):
if not number <= 1:
for i in range(2, number):
if (number % i) == 0:
print("Not prime")
break
else:
print("Integer must be greater than 1")
if __name__ == "__main__":
number = sys.argv[1]
calculate( int(number) )
Ora puoi eseguire il codice come comando:
$ python ./prime.py 4
Not a prime
E puoi convertirlo in Cython per usarlo come modulo:
>>> import prime
>>> prime.calculate(4)
Not prime
C Pitone
La conversione del codice da Python puro a C con Cython può essere utile. Questo articolo mostra come eseguire questa parte, ma ci sono funzionalità Cython che ti aiutano a ottimizzare il codice prima della conversione, opzioni per analizzare il codice per scoprire quando Cython interagisce con C e molto altro. Se stai usando Python, ma stai cercando di migliorare il tuo codice con codice C o approfondire la tua comprensione di come le librerie forniscono una migliore estensibilità rispetto agli script, o se sei semplicemente curioso di sapere come Python e C possono lavorare insieme, allora inizia sperimentando con Cython.