代码之家  ›  专栏  ›  技术社区  ›  Nicolas Dumazet

python c扩展:文档的方法签名?

  •  12
  • Nicolas Dumazet  · 技术社区  · 17 年前

    我正在编写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(超时,标志=无)

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

    2 回复  |  直到 9 年前
        1
  •  6
  •   Bluehorn    17 年前

    我发现这类事情的通常方法是:“使用源代码”。

    基本上,我假设Python的标准模块在可用时会使用这种特性。寻找源头( for example here )应该有帮助,但实际上即使是标准模块也会在自动输出后添加原型。这样地:

    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来源,情况仍然如此。该签名生成于 pydoc.py 在这里的python源代码中: pydoc.py . 从第1260行开始的相关摘录:

            if inspect.isfunction(object):
                args, varargs, varkw, defaults = inspect.getargspec(object)
                ...
            else:
                argspec = '(...)'
    

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

        2
  •  6
  •   Community Mohan Dere    9 年前

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

    python本身使用 Argument Clinic 动态生成签名。然后一些机械师创造了一个 __text_signature__ 这可以反省(例如 help )@马蒂·皮耶特很好地解释了这个过程。 this answer .

    实际上,您可以从python获得参数clinic,并以动态方式进行,但我更喜欢手动方式:向docstring添加签名:

    在你的情况下:

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

    此函数的docstring已定义 this file .

    重要的是要认识到 不可能用于python<3.4 你需要遵守一些规则:

    • 你需要包括 --\n\n 在签名定义行之后。

    • 签名必须在docstring的第一行。

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

    • 您只能提供一个签名。因此,如果你使用类似的东西,它就不起作用了:

      foo(a)
      foo(x, a, b)
      --
      
      Narrative documentation
      
    推荐文章