Python C 扩展:文档的方法签名?
我正在编写 C 扩展,并且我想让我的方法的签名可见以供内省。
static PyObject* foo(PyObject *self, PyObject *args) {
/* blabla [...] */
}
PyDoc_STRVAR(
foo_doc,
"Great example function\n"
"Arguments: (timeout, flags=None)\n"
"Doc blahblah doc doc doc.");
static PyMethodDef methods[] = {
{"foo", foo, METH_VARARGS, foo_doc},
{NULL},
};
PyMODINIT_FUNC init_myexample(void) {
(void) Py_InitModule3("_myexample", methods, "a simple example module");
}
现在,如果(构建后...)我加载模块并查看其帮助:
>>> import _myexample
>>> help(_myexample)
我将得到:
Help on module _myexample:
NAME
_myexample - a simple example module
FILE
/path/to/module/_myexample.so
FUNCTIONS
foo(...)
Great example function
Arguments: (timeout, flags=None)
Doc blahblah doc doc doc.
我想更具体并且能够替换 foo(...) by foo(timeout, flags=None)
我可以这样做吗? 如何?
I am writing C extensions, and I'd like to make the signature of my methods visible for introspection.
static PyObject* foo(PyObject *self, PyObject *args) {
/* blabla [...] */
}
PyDoc_STRVAR(
foo_doc,
"Great example function\n"
"Arguments: (timeout, flags=None)\n"
"Doc blahblah doc doc doc.");
static PyMethodDef methods[] = {
{"foo", foo, METH_VARARGS, foo_doc},
{NULL},
};
PyMODINIT_FUNC init_myexample(void) {
(void) Py_InitModule3("_myexample", methods, "a simple example module");
}
Now if (after building it...) I load the module and look at its help:
>>> import _myexample
>>> help(_myexample)
I will get:
Help on module _myexample:
NAME
_myexample - a simple example module
FILE
/path/to/module/_myexample.so
FUNCTIONS
foo(...)
Great example function
Arguments: (timeout, flags=None)
Doc blahblah doc doc doc.
I would like to be even more specific and be able to replace foo(...) by foo(timeout, flags=None)
Can I do this? How?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
已经过去 7 年了但是您可以包含 C 扩展函数和类的签名。
Python 本身使用 Argument Clinic 动态生成签名。 然后一些机制创建一个
__text_signature__
,并且可以对其进行内省(例如使用help
)。 @MartijnPieters 在这个答案中很好地解释了这个过程。您实际上可以从 python 获取参数诊所并以动态方式进行操作,但我更喜欢手动方式:将签名添加到文档字符串:
在您的情况下:
我在我的包中大量使用了它:
iteration_utilities/src
。 因此,为了证明它的工作原理,我使用了此包公开的 C 扩展函数之一:此函数的文档字符串定义为 此文件。
重要的是要认识到这对于 python 来说是不可能的。 3.4 并且您需要遵循一些规则:
您需要在签名定义行之后包含
--\n\n
。签名必须位于文档字符串的第一行。
签名必须有效,即
foo(a, b=1, c)
失败,因为无法在默认参数之后定义位置参数。您只能提供一个签名。 所以如果你使用类似的东西它就不起作用:
<前><代码>foo(a)
foo(x, a, b)
--
叙述性文档
It has been 7 years but you can include the signature for C-extension function and classes.
Python itself uses the Argument Clinic to dynamically generate signatures. Then some mechanics create a
__text_signature__
and this can be introspected (for example withhelp
). @MartijnPieters explained this process quite well in this answer.You may actually get the argument clinic from python and do it in a dynamic fashion but I prefer the manual way: Adding the signature to the docstring:
In your case:
I made heavy use of this in my package:
iteration_utilities/src
. So to demonstrate that it works I use one of the C-extension functions exposed by this package:The docstring for this function is defined this file.
It is important to realize that this isn't possible for python < 3.4 and you need to follow some rules:
You need to include
--\n\n
after the signature definition line.The signature must be in the first line of the docstring.
The signature must be valid, i.e.
foo(a, b=1, c)
fails because it's not possible to define positional arguments after arguments with default.You can only provide one signature. So it doesn't work if you use something like:
我查找此类问题的常用方法是:“使用源代码”。
基本上,我认为 python 的标准模块会在可用时使用这样的功能。 查看源代码(例如这里)应该有帮助,但事实上,即使标准模块也会在自动输出后添加原型。 像这样:
由于上游没有使用这样的功能,我认为它不存在。 :-)
好吧,我刚刚检查了当前的 python3k 源代码,情况仍然如此。 该签名是在 python 源代码中的 pydoc.py 中生成的:pydoc.py。 从第 1260 行开始的相关摘录:
inspect.isfunction 检查请求文档的对象是否是 Python 函数。 但 C 实现的函数被视为内置函数,因此您始终会得到
name(...)
作为输出。My usual approach to finding out about things like this is: "use the source".
Basically, I would presume that the standard modules of python would use such a feature when available. Looking at the source (for example here) should help, but in fact even the standard modules add the prototype after the automatic output. Like this:
So as upstream is not using such a feature, I would assume it is not there. :-)
Okay, I just checked current python3k sources and this is still the case. That signature is generated in
pydoc.py
in the python sources here: pydoc.py. Relevant excerpt starting in line 1260:inspect.isfunction checks if the object the documentation is requested for is a Python function. But C implemented functions are considered builtins, therefore you will always get
name(...)
as the output.如果它有帮助的话,我发现类似下面的东西可以提供类型签名并让 PyCharm 理解类型。
对于应该具有以下签名的函数(并且第二个参数是可选的):
我将在 PyMethodDef 的 ml_doc 字段中使用以下内容:
python 使用“\n--\n\n”之前的所有内容来填充方法上的
__text_signature__
。 其余部分进入__doc__
。 PyCharm 解析 __doc__ 以找出类型。:rtype:
行末尾的双换行符是 PyCharm 正确处理它所必需的,否则将附加以下描述。In case it is helpful, I have found that something like the following works to provide a type signature and also let PyCharm understand the typing.
For a function that should have the following signature (and where the second parameter is optional):
I would use the following in the ml_doc field of PyMethodDef:
Everything before the "\n--\n\n" is used by python to populate
__text_signature__
on the method. The rest goes into__doc__
. PyCharm parses__doc__
to figure out the types. The double newline at the end of the:rtype:
line is necessary for PyCharm to process it correctly, otherwise the following description gets annexed to it.