如何内省在Cython C扩展模块中定义的函数

问题描述:

Python的inspect模块似乎无法检查“内置”函数的签名,其中包含C扩展模块中定义的函数,如用Cython。有什么办法可以获得你在这个模块中定义的Python函数的签名,特别是在Cython中?我期望能够找到可用的关键字参数。如何内省在Cython C扩展模块中定义的函数

MWE:

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

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

inspect.signature(mwe.example) 

产量:

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

+1

为什么不能这样做? 'inspect.signature(all)'(例如提取['all']的签名)(https://docs.python.org/library/functions.html#all))很好用''。请提供一个[mcve],以便答案可以实际向您展示如何在*您的案例*中做到这一点。 – MSeifert

+2

[Python inspect.getargspec with built-in function]的可能重复](https://*.com/questions/11343191/python-inspect-getargspec-with-built-in-function) – DavidW

+1

也适用:https:// *.com/questions/1104823/python-c-extension-method-signatures-for-documentation – DavidW

我收回我的重复建议(说它是强加的sible ...)进一步调查。它似乎适用于最新版本的Cython(v0.23.4)和Python 3.4.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={})


the documentation is the compilation option "binding"这显然使这个细节更容易也提到了(虽然我并不需要它)。


我有一种感觉,这可能取决于相对近期改进inspect(可能this fix),所以如果你正在使用Python 2你可能是出于运气。


编辑:你的例子,如果你使用binding编译选项的工作原理:

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

我怀疑inline自动添加它(但代码做inline足够令人费解的是,我可以”无论如何找到证明)。您也可以将其设置为文件级选项。

+0

感谢大卫,我已经用MWE更新了这个问题,似乎没有与内联函数相反的导入工作。 – Gilly

+0

@Gilly请参阅编辑 - 这只是确保您使用'binding'的情况 – DavidW

+0

谢谢你!正是我在找什么。 – Gilly