2017-09-04 30 views
2

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://stackoverflow.com/questions/11343191/python-inspect-getargspec-with-built-in-function) – DavidW

+1

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

回答

2

我收回我的重複建議(說它是強加的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