关于python:如何内省cython c扩展模块中定义的函数

How to introspect a function defined in a Cython C extension module

python的inspect模块似乎无法检查"内置"函数的签名,这些函数包括C扩展模块中定义的函数,就像cython定义的那些函数一样。有没有办法获得您在这样一个模块中,特别是在cython中定义的python函数的签名?我希望能够找到可用的关键字参数。

MWE:

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

1
2
3
4
5
import pyximport; pyximport.install()                                                                                                                                        
import mwe                                                                                                                                                                    
import inspect                                                                                                                                                                

inspect.signature(mwe.example)

产量:

1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):                                                                                                                                          
  File"mwe_py.py", line 5, in <module>                                                                                                                                      
    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 <built-in function example>

在python 3.4.5和cython 0.24.1中


我已经撤回了我的重复建议(说这是不可能的…)进一步调查。它似乎可以与Cython(v0.23.4)和python 3.4.4的最新版本配合使用。

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

给出输出

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

文档中还提到了编译选项"binding",这显然使这个细节更容易访问(尽管我不需要它)。

我有一种感觉,这可能取决于最近对inspect所做的改进(可能是这个修复),所以如果您使用的是python 2,那么您可能会走运。

编辑:如果使用binding编译选项,则示例可以工作:

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

我怀疑inline会自动添加它(但是执行inline的代码非常复杂,我找不到任何证明)。也可以将其设置为文件级选项。