Расширение Python C:подписи методов для документации?

StackOverflow https://stackoverflow.com/questions/1104823

Вопрос

Я пишу расширения 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(тайм-аут, флаги=Отсутствуют)

Могу ли я это сделать?Каким образом?

Это было полезно?

Решение

Мой обычный подход к выяснению подобных вещей таков:"используй источник".

В принципе, я бы предположил, что стандартные модули python будут использовать такую функцию, когда она будет доступна.Глядя на источник (например, здесь) должно помочь, но на самом деле даже стандартные модули добавляют прототип после автоматического вывода.Вот так:

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

Итак, поскольку upstream не использует такую функцию, я бы предположил, что ее там нет.:-)

Хорошо, я только что проверил текущие исходники python3k, и это все еще так.Эта подпись генерируется в pydoc.py в источниках python здесь: pydoc.py.Соответствующий отрывок, начинающийся в строке 1260:

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

inspect.isfunction проверяет, является ли объект, для которого запрашивается документация, функцией Python.Но реализованные на C функции считаются встроенными, поэтому вы всегда получите name(...) в качестве выходного сигнала.

Другие советы

Прошло уже 7 лет но вы можете включить сигнатуру для функции расширения C и классов.

Сам Python использует Аргументированная Клиника для динамической генерации подписей.Затем некоторые механики создают __text_signature__ и это можно проанализировать (например, с помощью help).@MartijnPieters довольно хорошо объяснил этот процесс в этот ответ.

На самом деле вы можете получить аргумент clinic из 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.
[...]

Определена строка документации для этой функции этот файл.

Важно понимать, что это это невозможно для python < 3.4 и вам нужно следовать некоторым правилам:

  • Вам необходимо включить --\n\n после строки определения подписи.

  • Подпись должна быть в первой строке строки документа.

  • Подпись должна быть действительной, т.е. foo(a, b=1, c) завершается с ошибкой, потому что невозможно определить позиционные аргументы после аргументов с значением по умолчанию.

  • Вы можете предоставить только одну подпись.Таким образом, это не сработает, если вы используете что-то вроде:

    foo(a)
    foo(x, a, b)
    --
    
    Narrative documentation
    
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top