Cómo realizar una introspección de una función definida en un módulo de extensión Cython C

El módulo de inspect de Python no parece ser capaz de inspeccionar las firmas de las funciones “integradas”, que incluyen funciones definidas en los módulos de extensión C, como las definidas por Cython. ¿Hay alguna forma de obtener la firma de una función de Python que haya definido en dicho módulo, y específicamente en Cython? Estoy buscando ser capaz de encontrar los argumentos de palabras clave disponibles.

MWE:

 # mwe.pyx def example(a, b=None): pass 

y

 import pyximport; pyximport.install() import mwe import inspect inspect.signature(mwe.example) 

rendimientos

 Traceback (most recent call last): File "mwe_py.py", line 5, in  inspect.signature(mwe.example) File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 2063, in signature return _signature_internal(obj) File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 1965, in _signature_internal skip_bound_arg=skip_bound_arg) File "/nix/store/134l79vxb91w8mhxxkj6kb5llf7dmwpm-python3-3.4.5/lib/python3.4/inspect.py", line 1890, in _signature_from_builtin raise ValueError("no signature found for builtin {!r}".format(func)) ValueError: no signature found for builtin  

En Python 3.4.5 y Cython 0.24.1

Retiré mi sugerencia duplicada (diciendo que era imposible …) después de haber investigado más. Parece funcionar bien con versiones razonablemente recientes de Cython (v0.23.4) y Python 3.4.4.

 import cython import inspect scope = cython.inline("""def f(a,*args,b=False): pass """) print(inspect.getfullargspec(scope['f'])) 

da la salida

FullArgSpec(args=['a'], varargs='args', varkw=None, defaults=None, kwonlyargs=['b'], kwonlydefaults={'b': False}, annotations={})


También se menciona en la documentación la opción de comstackción ” binding ” que aparentemente hace que este detalle sea más accesible (aunque no lo necesitaba).


Tengo la sensación de que esto puede depender de las mejoras a las inspect realizadas recientemente (posiblemente esta solución ), por lo que si está usando Python 2 probablemente no tenga suerte.


Edición: su ejemplo funciona si utiliza la opción de comstackción de binding :

 import cython @cython.binding(True) def example(a, b=None): pass 

Sospecho que inline agrega automáticamente (pero el código para hacerlo en inline está lo suficientemente complicado como para que no pueda encontrar pruebas de eso de ninguna manera). También puede configurarlo como una opción de nivel de archivo.