Python C extension: method signatures for documentation?
我正在编写C扩展,我想让我的方法的签名可见以便进行自省。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | static PyObject* foo(PyObject *self, PyObject *args) { /* blabla [...] */ } PyDoc_STRVAR( foo_doc, "Great example function " "Arguments: (timeout, flags=None) " "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"); } |
现在,如果(在构建它之后…)我加载模块并查看其帮助:
1 2 | >>> import _myexample >>> help(_myexample) |
号
我会得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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(超时,标志=none)替换foo(…)。
我能做这个吗?怎么用?
它已经有7年了,但是您可以包含C扩展函数和类的签名。
python本身使用参数clinic动态生成签名。然后,一些机制创建一个
实际上,您可以从python获得参数clinic,并以动态方式进行,但我更喜欢手动方式:向docstring添加签名:
在您的情况下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | PyDoc_STRVAR( foo_doc, "foo(timeout, flags=None, /) " "-- " " " "Great example function " "Arguments: (timeout, flags=None) " "Doc blahblah doc doc doc."); |
我在包装中大量使用了这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> from iteration_utilities import minmax >>> help(minmax) Help on built-in function minmax in module iteration_utilities._cfuncs: minmax(iterable, /, key, default) Computes the minimum and maximum values in one-pass using only ``1.5*len(iterable)`` comparisons. Recipe based on the snippet of Raymond Hettinger ([0]_) but significantly modified. Parameters ---------- iterable : iterable The `iterable` for which to calculate the minimum and maximum. [...] |
。
此函数的docstring是为此文件定义的。
重要的是要认识到这对于python<3.4是不可能的,您需要遵循一些规则:
您需要在签名定义行之后包含
-- 。签名必须在docstring的第一行。
签名必须有效,即
foo(a, b=1, c) 失败,因为不能在默认参数之后定义位置参数。您只能提供一个签名。因此,如果你使用类似的东西,它就不起作用了:
1
2
3
4
5foo(a)
foo(x, a, b)
--
Narrative documentation
我发现这类事情的通常方法是:"使用源代码"。
基本上,我假设Python的标准模块在可用时会使用这种特性。查看源代码(例如这里)应该会有所帮助,但实际上,即使是标准模块也会在自动输出之后添加原型。这样地:
1 2 3 4 5 6 7 | torsten@pulsar:~$ python2.6 >>> import fcntl >>> help(fcntl.flock) flock(...) flock(fd, operation) Perform the lock operation op on file descriptor fd. See the Unix [...] |
因此,由于上游不使用这样的功能,我假设它不在那里。-)
好吧,我刚查了一下目前的Python3k来源,情况仍然如此。该签名在这里的python源中的
1 2 3 4 5 | if inspect.isfunction(object): args, varargs, varkw, defaults = inspect.getargspec(object) ... else: argspec = '(...)' |
号
inspect.is function检查文档请求的对象是否是python函数。但是C实现的函数被认为是内置的,因此您将始终得到