C / C ++ para escribir módulos de extensión de Python

directorio

1 Introducción

1.1 usos Python y ventajas de los módulos de ampliación

1.2 Diseño proceso de extensión

2 guión setup.py

interfaz 3 función, paso de parámetros, simplemente valor de retorno

3.1 interfaz de la función

paso 3.2 parámetro

3.3 valor de retorno sencillo

4-tuplas, listas, diccionarios, tampón

5 manejo de excepciones, el contador de referencias

5.1 Lanza una excepción

5.2 recuento de referencia

6 GIL y multihilo

  1. breve introducción

En este trabajo se registra el módulo de extensión de Python desarrollo utilizado en la práctica, de manera que el lector pueda utilizar módulos de extensión de Python bajo costo para mejorar el rendimiento de las aplicaciones.

El texto no se extiende módulos tutorial introductorio, sino por una cierta idea de los módulos de expansión, pero no ha sido capaz de aplicar de manera efectiva los lectores.

1.1 usos Python y ventajas de los módulos de ampliación

módulos de extensión de Python de varios usos comunes y ventajas:

mejoras en el rendimiento

Python módulo de extensión usando C / C ++ para escribir, calcular su rendimiento es C / C ++ al mismo nivel. pérdida de rendimiento en la interfaz de comunicación entre lenguajes a un pequeño insignificante, puede proporcionar un apoyo muy bueno el rendimiento. tales típico paquete Numpy para la computación científica, sus cálculos matemáticos subyacentes denominan bibliotecas de terceros, el rendimiento es el mismo nivel.

El uso de la potencia de computación de núcleos múltiples

Mediante el control de la extensión de la GIL, potencia de cálculo se puede utilizar en la CPU de varios núcleos, no se limita a los límites del programa de Python puros de un solo núcleo. ¿Cuántas núcleo multi-hilo puede ser personalizado para su uso.

El aislamiento y componentes modulares del sistema

Por cada función de C / C ++ proporciona una interfaz de Python que no se comparte entre la función de cualquier estado, para lograr una buena puesta a punto de aislamiento, contribuir al desarrollo y prueba. Y debido a que todos los parámetros pasados ​​por Python, fácil de imprimir y interrumpido debugability se ha mejorado mucho.

El uso de bibliotecas de terceros

No cada biblioteca tiene soporte para Python, entonces usted necesita para escribir su propio módulo de extensión para el sistema de acoplamiento. Pero moderno gran biblioteca popular, tiene muchos módulos oficiales de extensión de Python, por lo que la calidad de la aplicación se ha mejorado en gran medida, como OpenCV y típico PyCUDA.

1.2 Diseño proceso de extensión

setup.py escritura: la escritura de configuración del módulo de extensión de la meta-información

Introducir los archivos de cabecera necesarios: varios archivos de cabecera utilizan principalmente para Python.h

tabla de funciones de diseño de Exportación: Exportación a usar la tabla de funciones Python

módulos de función de inicialización: los pasos necesarios varios inicialización

  1. guión setup.py

setup.py guiones se utilizan para construir la configuración del módulo de expansión. Hay muchos en línea simple da un proyecto más ejemplos prácticos y son los siguientes:

plataforma de importación

distutils.core de configuración de importación, Extensión

de distutils sysconfig importación

cfg_vars = sysconfig.get_config_vars ()

Si 'OPT' en cfg_vars:

cfg_vars [ 'OPT'] = cfg_vars [ 'OPT'] reemplazar. ( '- Wstrict-prototipos', '')

mod_expy = Extension ( 'libxx.expy',

fuentes = [ 'libxx / expy.c',],

bibliotecas = [ 'jpeg',],

include_dirs = [ '/ opt / local / include',],

library_dirs = [ '/ opt / / lib local',],

define_macros = [( 'MAJOR_VERSION', '1'), ( 'minor_version', '0')],

)

# Compilador para distinguir entre las diferentes plataformas

Si platform.system () == 'Darwin':

os.environ [ 'ARCHFLAGS'] = '- x86_64 arco'

extmodlist = [mod_expy,]

elif platform.system () = 'Linux':

os.environ [ 'ARCHFLAGS'] = '- Arch i386 -arch x86_64'

extmodlist = [mod_expy,]

más:

aumentar RuntimeError ( 'sistema Desconocido () =% s' % repr (platform.system ()))

configuración (nombre = 'libxx',

version = '1.0',

Descripción = 'libxx-pitón',

autor = 'gashero',

author_email='[email protected]',

paquetes = [ 'libxx',],

ext_modules = extmodlist,

url = 'http: //example.com/',

long_description = 'xxxxxx xxxxxx',

)

Hola mundo con respecto a los diversos niveles de setup.py. Como la secuencia de comandos para agregar funciones prácticas:

Proporciona una compilación más amplios parámetros, tales como las definiciones de macros específicas son compilados, los parámetros del compilador

Referirse a otras bibliotecas de terceros

Compilar distinguir diferentes plataformas, Linux y Mac diferenciados

Liga de Campeones le ofrece una más completa información de metadatos

Por lo general, hemos escrito el tamaño del módulo de extensión no es muy grande, como lo suficientemente guión setup.py de usar. Si se trata de módulos de expansión de múltiples archivos de origen más complejos, sólo para seguir aumentando los objetos de extensión.

  1. interfaz de la función, paso de parámetros, sólo tiene valor de retorno

3.1 interfaz de la función

Se utiliza para definir la función y pasa a la llamada Python. Es la instancia de tipo PyMethodDef definir. Un ejemplo es el siguiente:

estática PyMethodDef expyMethods [] = {

{ “ADD”, expy_add, METH_VARARGS, “Añadir 2 número”},

{NULL, NULL, 0, NULL}

};

Esta definición de los cuatro campos en el tercer campo para invocar la función decidido, en caso dado de la siguiente manera:

METH_VARARGS: formar una pluralidad de parámetros, el juego más común

METH_NOARGS: ningún parámetro, que se utilizan para la función de clase de salida

METH_VARARGS | METH_KEYWORDS: tienen ambos parámetros anónimos y argumentos de palabras clave

El último campo es la función del documento para la función de ayuda () se muestra.

paso 3.2 parámetro

Función se define mediante los parámetros que contienen los parámetros clave anónimos son diferentes, ambos de los siguientes:

estática PyObject * func (* PyObject auto, PyObject * args);

estática PyObject * FUNC (PyObject * uno mismo, PyObject * args, PyObject ** kwargs);

Si no hay contenidos correspondientes se pasan NULL. Para la función de los módulos, no es el método de objeto, no puede centrarse en uno mismo.

El uso de los parámetros del proceso de resolución PyArg_ParseTuple (PyArg_ParseTupleAndKeywords) y (). Con una cadena que describe la lista de parámetros, a continuación, la dirección de referencia de cada objeto entrante.

Teniendo en cuenta los parámetros y tipos de valor de retorno puede no ser mutuamente agradable y en general se recomienda no entregar el tipo de:

Relevante arquitectura numérico tipo, tal como int, largo, pero la longitud del tipo de transmisión digital conocido

Estructura, debido a la ubicación de la estructura de almacenamiento real puede tener ciclo de vida, lo mismo se aplica a los objetos C ++

puntero de dirección, porque la arquitectura está relacionada, los punteros de función que comprende

De hecho, necesidad de pasar la dirección de la estructura, cuando el objeto se recomienda generalmente a los objetos de escritura en los módulos de expansión, aunque más difícil, pero la compatibilidad será mucho mejor.

No deje nada en el programa en C / C ++, como las variables globales.

3.3 valor de retorno sencillo

valor de retorno de la función debe ser un objeto Python.

función simple devuelve se consigue ningún valor puede ser utilizado directamente en el extremo de una función macro:

Py_RETURN_NONE;

Esta función de salida simple que no es ningún problema.

Se puede utilizar un poco más complicado Py_BuildValue () Después de una cadena se pasa en cada formato de los valores descritos, estructuras de datos más complejas se pueden construir.

  1. Tuplas, listas, diccionarios, tampón

El papel de las tuplas en Python son inmutables, que por el contenido de Python es muy amable, y el rendimiento es mejor que una lista.

El valor de la lista es que no se puede fijar la longitud de almacenamiento de contenidos. Por ejemplo, la biblioteca de C / C ++ devolverá una gran cantidad de contenido de terceros usados ​​de una manera iterativa. Al comienzo de la función no sabe cuántos objetos son capaces de volver, sólo el lado de cada llamada para obtener el siguiente objeto. En este caso, es adecuado para crear una lista, se añade a continuación, cada elemento método append () con. Por ejemplo:

PyObject * retlist = PyList_New (0); // crear una longitud de la cola 0

mientras que (POS) {

PyList_Append (retlist, Py_BuildValue ( "{}"));

pos = posi-> siguiente;

}

Diccionario también se puede usar para devolver el contenido de una sola estructura. Se trata de la estructura C / C ++ de cada campo como un elemento para fijar el diccionario y retorno. Legibilidad de este enfoque será bueno.

Ejemplos del uso de la información de almacenamiento dict, string clave:

PyObject * fmtinfo = PyDict_New ();

PyDict_SetItemString (fmtinfo, "índice", PyInt_FromLong (1));

No se recomienda volver a la lista de dict, después de todo, consumir más rendimiento. Por la pluralidad de retorno de las estructuras, de una manera más conveniente en la lista o tupla.

Uso Py_BuildValue (longitud del contenido que el rendimiento estimado) más adecuado.

Para no necesita comprender el contenido de tipos de tampón cadena puede ser utilizado, y el rendimiento sería más que str Guardar tipo de memoria. diferencia str con respecto al tipo de tipo de tampón está, el sistema no comprueba los contenidos de las mismas dos cadenas de amortiguamiento. Y el sistema str se asegurará de que no habrá repetición de la cadena. Este cálculo es a llevar mucho tiempo.

Después de que el nuevo buffer, un puntero para conseguir sus ejemplos operativos:

Py_ssize_t buflen = 1,000, _buflen;

bufptr void *;

PyObject * buf = PyBuffer_New (buflen);

si (PyObject_AsWriteBuffer (buf, y bufptr, y _buflen) <0) {

NULL regresar;

}

  1. El manejo de excepciones, el contador de referencias

5.1 Lanza una excepción

Se utiliza para notificar Python, se ha producido un error en una función. Varios de uso común incorporado excepciones:

PyExc_ZeroDivisionError: por 0

IO error: PyExc_IOError

PyExc_TypeError: el tipo de error, tales como el tipo incorrecto de parámetros

PyExc_ValueError: rango de error de los valores

PyExc_RuntimeError: error de ejecución

PyExc_OSError: error al interactuar con diferentes sistemas operativos

Usted puede lanzar una excepción a su gusto. El método real produce una excepción, tales como:

si (r <0) {

PyErr_SetString (PyExc_RuntimeError, “Tiempo de ejecución no!”);

NULL regresar;

}

excepción veces espero tirado contiene algunos parámetros, tales como códigos de error, para facilitar una mejor depuración. Se puede utilizar el siguiente método:

si (r <0) {

PyErr_Format (PyExc_OSError, “ERROR [% d] =% s”,

errno, strerror (errno));

}

Una variedad de biblioteca de C / C ++ hace un amplio uso de un código incorrecto, a fin de utilizar el método anterior se utiliza ampliamente. Vea las excepciones de error función lanzados en Python y contiene el código de error es habitual para escribir programas pura C / C ++ para mover el accidente y más bella. El proceso de escribir módulos de extensión hace que este trabajo estandarizado.

5.2 recuento de referencia

contador de referencia extendida es muy mágico, y es un módulo muy criticada problema.

El uso real, cada API Python indicará su funcionamiento en la cuenta de referencia en el documento. Los préstamos no está cambiando la cuenta de referencia, y la referencia es aumentar 1.

Para evitar las náuseas cada vez que encontrar el contenido, podría usar algunas funciones de fácil. Por ejemplo Py_BuildValue () se pasa directamente a los datos C / C ++, dentro de la cual es responsable de generar estructuras de datos complejas, y gestionar la cuenta de referencia.

tupla, tampón de gestión de cuenta de referencia es también más simple que la lista, str debe ser recomendada.

  1. Gil y multihilo

Python GIL es limitar el uso de la causa directa de núcleos múltiples, la causa es interna intérprete Python tiene algunas variables globales, tales como el manejo típica excepción. Y hay una gran cantidad de módulos de terceros en la API de Python y el uso de estas variables globales que no pueden ser mejoradas GIL ha habido avances.

Nivel en el módulo de expansión es el GIL liberado, de modo que la parte posterior control de la CPU a la de Python, y la corriente C / C ++ código también pueden continuar. Sin embargo, es importante señalar que llamar a cualquier API de Python debe llevarse a cabo bajo el control del GIL. Así liberar GIL antes de realizar tareas computacionalmente intensivas, después de la finalización del cálculo, vuelva a aplicar GIL, entonces el valor de retorno y el manejo de excepciones.

La primera solicitud de liberación y GIL escrito en el módulo de expansión de funciones en:

estática PyObject * * Fun (PyObject uno mismo, PyObject * args) {

// ...

PyThreadState * _save;

_save = PyEval_SaveThread ();

bloquear();

PyEval_RestoreThread (_save);

// ...

}

El método también necesita llamada durante PyEval_InitThreads inicialización del módulo ().

Otro método es simple y más:

Py_BEGIN_ALLOW_THREADS;

// operación potencialmente bloqueo

Py_END_ALLOW_THREADS;

Por lo tanto, un método simple es utilizar la computación de núcleos múltiples, la tarea dividida en una pluralidad de piezas pequeñas, cada una de las piezas pequeñas se colocan en un hilo conductor. Subproceso llama el módulo de expansión de funciones para calcular, comunicados de la función de cálculo el cálculo real GIL.

De esta manera se puede utilizar con eficacia Python para manejar hilos, sin el uso de pthread tales problemas en C / C ++, la única necesidad de hacer el más simple de calcular muy bien.

Publicados 261 artículos originales · ganado elogios 4 · Vistas 4263

Supongo que te gusta

Origin blog.csdn.net/it_xiangqiang/article/details/105206265
Recomendado
Clasificación