Cómo incluir la biblioteca externa con el paquete de la rueda de Python

Quiero crear un paquete para python que incruste y use una biblioteca externa ( .so ) en Linux usando el módulo cffi.

¿Hay alguna forma estándar de incluir el archivo .so en el paquete de Python?

El paquete se utilizará solo internamente y no se publicará en pypi.

Creo que los paquetes de Wheel son la mejor opción: crearían un paquete específico de la plataforma con todos los archivos listos para ser copiados, por lo que no habrá necesidad de construir nada en los entornos de destino.

Puede usar auditwheel para inyectar las bibliotecas externas en la rueda:

reparación auditwheel: copia estas bibliotecas compartidas externas en la propia rueda, y modifica automáticamente las entradas RPATH apropiadas para que estas bibliotecas se seleccionen en tiempo de ejecución. Esto logra un resultado similar como si las bibliotecas se hubieran enlazado estáticamente sin requerir cambios en el sistema de comstackción. Se recomienda a los empaquetadores que la agrupación, como la vinculación estática, puede implicar problemas de derechos de autor.

Puede pre-construir la biblioteca externa de c ++ ejecutando típicamente lo siguiente:

 ./configure && make && make install 

Esto generará un archivo my_external_library.so y lo instalará en la ruta apropiada. Sin embargo, deberá asegurarse de que la ruta de la biblioteca esté configurada correctamente para que la rueda de auditoría descubra la dependencia que falta.

 export LD_LIBRARY_PATH=/usr/loca/lib 

Luego puedes construir la rueda de python ejecutando:

 python setup.py bdist_wheel 

Finalmente, puede reparar la rueda, que inyectará my_external_library.so en el paquete.

 auditwheel repair my-python-wheel-1.5.2-cp35-cp35m-linux_x86_64.whl 

He aplicado con éxito los pasos anteriores a la biblioteca de python confluent-kafka-python que tiene una dependencia de c / c ++ requerida en librdkafka .

Las ruedas son la forma estándar de distribuir paquetes de Python, pero existe un problema cuando tiene módulos de extensión que dependen de otros. Esto se debe a que se utiliza el enlazador dynamic de Linux normal y que solo se ve en /usr/lib o /usr/local/lib . Este es un problema al instalar una rueda en un virtualenv .

Por lo que sé, tienes tres opciones:

  • Enlace estático, por lo que el ‘wrapper’ no depende de nada más;
  • usando ctypes para envolver el so directamente desde Python;
  • Divida la distribución en una rueda con el código y la envoltura de Python, y un RPM o DEB por separado para instalarlo en /usr/lib o /usr/local/lib .

Una rueda puede funcionar si incluye al dependiente como un archivo de datos para almacenar en /lib e instalarlo en el entorno de Python raíz (no lo he intentado), pero esto se romperá si alguien intenta instalar la rueda en un virtualenv ( lo intenté).