tutorial python python-2.7 cython python-import python-c-extension

python - tutorial - Paquete de Cython con__init__. Pyx: ¿Posible?



cython tutorial (2)

¿Es posible crear un paquete de Python 2.7 usando __init__.pyx (compilado a __init__.so )? ¿Si es así, cómo? No he tenido suerte para que funcione.

Esto es lo que he intentado:

  • setup.py :

    #!/usr/bin/env python from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext foo = Extension(name=''foo.__init__'', sources=[''foo/__init__.pyx'']) bar = Extension(name=''foo.bar'', sources=[''foo/bar.pyx'']) setup(name=''foo'', packages = [''foo''], cmdclass={''build_ext'':build_ext}, ext_modules = [foo, bar])

  • foo/__init__.pyx :

    import foo.bar cpdef hello_world(): print "hello world" foo.bar.blah()

  • foo/bar.pyx :

    cpdef blah(): print "blah"

Lo anterior tiene el siguiente comportamiento:

$ python -c ''import foo; foo.hello_world()'' Traceback (most recent call last): File "<string>", line 1, in <module> ImportError: No module named foo

Vi el problema de Python # 15576 que fue corregido por este Hg commit . Mirando el compromiso equivalente de Git en el espejo Git del repositorio de Python Hg, veo que el compromiso es alcanzable desde la etiqueta de Python v2.7.5 (y todas las versiones posteriores de v2.7.x). ¿Hubo una regresión?


De acuerdo con esta publicación de la lista de correo realmente vieja , funciona si también tienes un archivo __init__.py (el archivo __init__.py no se usa, pero parece ser necesario para que el directorio se trate como un módulo, y por lo tanto el __init__.so archivo para ser cargado).

Si agrego __init__.py :

# an exception just to confirm that the .so file is loaded instead of the .py file raise ImportError("__init__.py loaded when __init__.so should have been loaded")

entonces tu ejemplo funciona en Linux Python 2.7.3:

$ python -c ''import foo; foo.hello_world()'' hello world blah

Esto tiene todos los signos de una caja de esquina con errores, por lo que probablemente no sea recomendable. Tenga en cuenta que en Windows esto no parece funcionar para mí dando

ImportError: DLL load failed: %1 is not a valid Win32 application.

Adición (para un pequeño contexto adicional):

Este comportamiento no parece estar explícitamente documentado. En la descripción original de paquetes de alrededor de la era Python 1.5 dicen:

sin __init__.py , un directorio no se reconoce como un paquete

y

Consejo: el orden de búsqueda está determinado por la lista de sufijos devueltos por la función imp.get_suffixes() . Por lo general, los sufijos se buscan en el siguiente orden: ".so", "module.so", ".py", ".pyc". Los directorios no aparecen explícitamente en esta lista, pero preceden a todas las entradas en él.

El comportamiento observado es sin duda consecuente con esto: __init__.py necesitó tratar un directorio como un paquete, pero el archivo .so se cargó con preferencia al archivo .py, pero no es ambiguo.

Desde el punto de vista de Cython, este comportamiento parece haberse usado para compilar la biblioteca estándar (en cuyo caso __init__.py siempre habría estado presente), o en los casos dados https://github.com/cython/cython/blob/master/tests/build/package_compilation.srctree (y algunos otros ejemplos también). En estos, el archivo "srctree" parece expandirse a una variedad de carpetas que contienen __init__.py (y otros archivos) y luego se compilan. Es posible que solo tener __init__.so simplemente nunca se haya probado.


Intenta usar una importación relativa.

en __init__ :

from . import bar

También podría ser from . import foo from . import foo . No he usado pitón 2 cython en un tiempo.