【问题标题】:Python C extension: method signatures for documentation?Python C 扩展:文档的方法签名?
【发布时间】:2010-11-09 10:36:45
【问题描述】:

我正在编写 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(...) 替换为 foo(timeout, flags=None)

我可以这样做吗?怎么样?

【问题讨论】:

    标签: python documentation python-c-api


    【解决方案1】:

    已经 7 年了但您可以包含 C 扩展函数和类的签名

    Python 本身使用Argument Clinic 来动态生成签名。然后一些机制创建一个__text_signature__,这可以被内省(例如help)。 @MartijnPieters 在 this answer 中很好地解释了这个过程。

    您实际上可以从 python 获取参数诊所并以动态方式进行,但我更喜欢手动方式:将签名添加到文档字符串:

    在你的情况下:

    PyDoc_STRVAR(
        foo_doc,
        "foo(timeout, flags=None, /)\n"
        "--\n"
        "\n"
        "Great example function\n"
        "Arguments: (timeout, flags=None)\n"
        "Doc blahblah doc doc doc.");
    

    我在我的包中大量使用了这个:iteration_utilities/src。因此,为了证明它的工作原理,我使用了此包公开的 C 扩展函数之一:

    >>> 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.
    [...]
    

    此函数的文档字符串定义为this file

    重要的是要意识到这对于python 是不可能的,您需要遵循一些规则:

    • 您需要在签名定义行之后包含--\n\n

    • 签名必须在文档字符串的第一行。

    • 签名必须有效,即foo(a, b=1, c) 失败,因为无法在默认参数之后定义位置参数。

    • 您只能提供一个签名。因此,如果您使用以下内容,则它不起作用:

      foo(a)
      foo(x, a, b)
      --
      
      Narrative documentation
      

    【讨论】:

    • @Eric 可以,只要符合我上面提到的__text_signature__的规则即可。
    • 听起来像是 numpy 需要补丁的东西
    【解决方案2】:

    我通常的查找此类事情的方法是:“使用源代码”。

    基本上,我认为 python 的标准模块会在可用时使用这样的功能。查看源代码(for example here)应该会有所帮助,但实际上即使是标准模块也会在自动输出后添加原型。像这样:

    torsten@pulsar:~$ python2.6
    >>> 导入 fcntl
    >>> 帮助(fcntl.flock)
    群(...)
        羊群(fd,操作)
    
        对文件描述符 fd 执行锁定操作 op。参见 Unix [...]
    

    所以上游没有使用这样的功能,我会假设它不存在。 :-)

    好的,我刚刚检查了当前的 python3k 源,情况仍然如此。该签名在此处的 python 源代码中的pydoc.py 中生成:pydoc.py。从第 1260 行开始的相关摘录:

    如果检查.isfunction(对象): 参数,可变参数,varkw,默认值 = inspect.getargspec(object) ... 别的: argspec = '(...)'

    inspect.isfunction 检查请求文档的对象是否是 Python 函数。但 C 实现的函数被视为内置函数,因此您将始终得到 name(...) 作为输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-23
      • 1970-01-01
      • 2017-01-31
      • 2011-09-09
      • 2016-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多