Creación de un paquete Python para un módulo de solo extensión C que está pre-construido

Quiero crear un paquete para un proyecto que no contenga ningún archivo fuente .py , pero que esté completamente implementado como una extensión de Python C (que resulta en un .so ). Además, suponga que .so ya está creado por un proceso de comstackción separado (por ejemplo, CMake).

Sé que setuptools / distutils requiere mínimamente una estructura de directorios:

  • mymodule
    • __init__.py

Pero lo que realmente quiero es que mi mymodule sea ​​proporcionado por una extensión C (por ejemplo, mymodule.so ) de tal manera que después de instalar el paquete, import mymodule tenga el mismo efecto que importar directamente mymodule.so .

Sé que podría tener este tipo de estructura de directorio:

  • mymodule
    • __init__.py
    • mymodule_native.so

y que __init__.py sea:

 from mymodule_native import * 

Este tipo de trabajo, pero un objeto A importado de mymodule realmente se verá como mymodule.mymodule_native.A .

¿Hay una manera más directa?

Es posible si la extensión está configurada por setuptools.

Por ejemplo:

 from setuptools import setup, Extension extension = Extension('mymodule', sources=[<..>]) setup('mymodule', ext_modules=[extension]) 

Una vez instalada, la extensión está disponible como import mymodule . Tenga en cuenta que find_packages no se utiliza.

Esto debe ser realizado por setuptools, ya que de lo contrario requeriría una configuración de packages si no se proveen ext_modules .

Sin embargo , esto hace que el módulo .so se instale directamente en el directorio de site-packages y entrará en conflicto con cualquier módulo de Python que no sea de extensión del mismo nombre.

Esto generalmente se considera una mala práctica y la mayoría de las bibliotecas usan un módulo Python simple con un solo __init__.py , bajo el cual la extensión está disponible.

En el futuro, por ejemplo, puede agregar código python a su módulo y desear separar el código python puro del código de extensión. O quizás desee agregar más de una extensión, lo que no es posible de esta manera, al menos no manteniendo el mismo nombre de paquete.

Así que una estructura como mymodule. y mymodule.my_extension tiene sentido.

Personalmente tendría espacios de nombres separados para el código de extensión frente al código de Python y no lo haría from import * en __init__.py .