如何内省 Cython C 扩展模块中定义的函数
How to introspect a function defined in a Cython C extension module
Python 的 inspect
模块似乎无法检查 "built-in" 函数的签名,其中包括 C 扩展模块中定义的函数,例如由赛通。有什么方法可以获取您在此类模块中定义的 Python 函数的签名,特别是在 Cython 中?我希望能够找到可用的关键字参数。
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 中
经过进一步调查,我撤回了重复的建议(说这是不可能的...)。它似乎适用于最新版本的 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
的代码非常复杂,我无法找到任何一种方式的证据)。您也可以将其设置为文件级选项。
当 运行 代码已被 cythonized 时,上面使用绑定装饰器的答案对我有用。但是,当我在 Django 2.2 应用程序中 运行 相同的代码时,该应用程序将在启动时失败,并出现 cython 没有属性 'binding' 的错误。为避免这种情况,我在包含 cythonized 函数的文件顶部添加了此 "special cython header",如记录 here 以实现相同的结果。
# cython: binding=True
def example(a, b=None):
pass
Python 的 inspect
模块似乎无法检查 "built-in" 函数的签名,其中包括 C 扩展模块中定义的函数,例如由赛通。有什么方法可以获取您在此类模块中定义的 Python 函数的签名,特别是在 Cython 中?我希望能够找到可用的关键字参数。
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 中
经过进一步调查,我撤回了重复的建议(说这是不可能的...)。它似乎适用于最新版本的 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
的代码非常复杂,我无法找到任何一种方式的证据)。您也可以将其设置为文件级选项。
当 运行 代码已被 cythonized 时,上面使用绑定装饰器的答案对我有用。但是,当我在 Django 2.2 应用程序中 运行 相同的代码时,该应用程序将在启动时失败,并出现 cython 没有属性 'binding' 的错误。为避免这种情况,我在包含 cythonized 函数的文件顶部添加了此 "special cython header",如记录 here 以实现相同的结果。
# cython: binding=True
def example(a, b=None):
pass