¿Qué es Cython?
Es un compilador estático de optimización tanto para el lenguaje de programación Python como para el lenguaje de programación extendido Cython. Se utiliza para facilitar la escritura de extensiones C para Python tan fácilmente como el mismo Python.
Viene con muchas características útiles :
- Escribir un código de Python que llama de un lado a otro desde y hacia el código C/C++.
- Fácil ajuste del código Python legible en el rendimiento C simple mediante la adición de declaraciones de tipo estático.
- Uso de depuración de nivel de código fuente combinado para encontrar errores en código Python, Cython y C dado.
- Interacción eficiente con grandes conjuntos de datos, por ejemplo, utilizando arrays NumPy multidimensionales.
- Integración con código y datos existentes de bibliotecas y aplicaciones de bajo nivel o alto rendimiento.
Hacer una extensión con Cython es una tarea difícil de realizar. Al hacerlo, es necesario crear una colección de funciones contenedoras. Suponiendo que el código de trabajo que se muestra se haya compilado en una biblioteca C llamada libwork . El siguiente código creará un archivo llamado csample.pxd
.
Código #1:
# cwork.pxd # # Declarations of "external" C # functions and structures cdef extern from "work.h": int gcd(int, int) int divide(int, int, int *) double avg(double *, int) nogil ctypedef struct Point: double x double y double distance(Point *, Point *)
En Cython, el código anterior funcionará como un archivo de encabezado C. La declaración inicial cdef extern from "work.h"
declara el archivo de encabezado C requerido. Las declaraciones que siguen se toman del encabezado. El nombre de este archivo es cwork.pxd
. El siguiente objetivo es crear un work.pyx
archivo que definirá contenedores que conecten el intérprete de Python con el código C subyacente declarado en el cwork.pxd
archivo.
Código #2:
# work.pyx # Import the low-level C declarations cimport cwork # Importing functionalities from Python # and the C stdlib from cpython.pycapsule cimport * from libc.stdlib cimport malloc, free # Wrappers def gcd(unsigned int x, unsigned int y): return cwork.gcd(x, y) def divide(x, y): cdef int rem quot = cwork.divide(x, y, &rem) return quot, rem def avg(double[:] a): cdef: int sz double result sz = a.size with nogil: result = cwork.avg(<double *> &a[0], sz) return result
Código #3:
# Destructor for cleaning up Point objects cdef del_Point(object obj): pt = <csample.Point *> PyCapsule_GetPointer(obj, "Point") free(<void *> pt) # Create a Point object and return as a capsule def Point(double x, double y): cdef csample.Point * p p = <csample.Point *> malloc(sizeof(csample.Point)) if p == NULL: raise MemoryError("No memory to make a Point") p.x = x p.y = y return PyCapsule_New(<void *>p, "Point", <PyCapsule_Destructor>del_Point) def distance(p1, p2): pt1 = <csample.Point *> PyCapsule_GetPointer(p1, "Point") pt2 = <csample.Point *> PyCapsule_GetPointer(p2, "Point") return csample.distance(pt1, pt2)
Finalmente, para construir el módulo de extensión, cree un work.py
archivo.
Código #4:
# importing libraries from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext ext_modules = [Extension('work', ['work.pyx'], libraries=['work'], library_dirs=['.'])] setup(name = 'work extension module', cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules)
Código #5: Construcción del módulo resultante para la experimentación.
bash % python3 setup.py build_ext --inplace running build_ext cythoning work.pyx to work.c building 'work' extension gcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/include/python3.3m -c work.c -o build/temp.macosx-10.6-x86_64-3.3/work.o gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.6-x86_64-3.3/work.o -L. -lwork -o work.so bash %
Ahora, tenemos un módulo de extensión work.so
. Vamos a ver cómo funciona.
Código #6:
import sample print ("GCD : ", sample.gcd(12, 8)) print ("\nDivision : ", sample.divide(42,10)) import array arr = array.array('d',[1,2,3]) print ("\nAverage : ", sample.avg(a) pt1 = sample.Point(2,3) pt2 = sample.Point(4,5) print ("\npt1 : ", pt1) print ("\npt2 : ", pt2) print ("\nDistance between the two points : ", sample.distance(pt1, pt2))
Producción :
GCD : 4 Division : (4, 2) Average : 2.0 pt1 : <capsule object "Point" at 0x1005d1e70> pt2 : <capsule object "Point" at 0x1005d1ea0> Distance between the two points : 2.8284271247461903
En un alto nivel, el uso de Cython sigue el modelo de C. Los archivos .pxd simplemente contienen definiciones de C (similares a .h
los archivos) y los .pyx
archivos contienen implementación (similar a un .c
archivo). Cython utiliza la instrucción cimport para importar definiciones desde un .pxd
archivo. Esto es diferente a usar una declaración de importación de Python normal, que cargaría un módulo de Python normal.
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA