Python C estensione: Metodo di firme per la documentazione?
-
12-09-2019 - |
Domanda
Le scrivo estensioni C, e mi piacerebbe fare la firma dei miei metodi visibile per l'introspezione.
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");
}
Ora, se (dopo costruirlo ...) che carico il modulo e guardo il suo aiuto:
>>> import _myexample
>>> help(_myexample)
mi metterò:
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.
Mi piacerebbe essere ancora più specifici ed essere in grado di sostituire foo (...) di foo (timeout, flags = None)
Come posso fare? Come?
Soluzione
Il mio approccio al solito per scoprire su cose come questo è: "utilizzare la fonte"
.Fondamentalmente, voglio presumere che i moduli standard di pitone userebbero tale caratteristica quando disponibile. Guardando alla fonte ( per esempio qui ) dovrebbe aiutare, ma in realtà anche i moduli standard aggiungere il prototipo dopo l'uscita automatica. In questo modo:
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 [...]
Quindi, come a monte non sta usando una tale funzione, io suppongo che non c'è. : -)
Va bene, ho appena controllato le fonti python3k attuali e questo è ancora il caso. Che la firma è generato in pydoc.py
nelle fonti pitone qui: pydoc.py . Rilevante stralcio di partenza in linea 1260:
if inspect.isfunction(object): args, varargs, varkw, defaults = inspect.getargspec(object) ... else: argspec = '(...)'
inspect.isfunction verifica se l'oggetto della documentazione è richiesta per è una funzione Python. Ma C implementato funzioni sono considerati i comandi incorporati, quindi avrai sempre name(...)
come uscita.
Altri suggerimenti
E 'stato 7 anni ma è possibile includere la firma per la funzione C-estensione e le classi .
Python stesso utilizza la Clinica rel="noreferrer"> argomento per generare dinamicamente le firme. Poi alcuni meccanici creano __text_signature__
e questo può essere introspected (ad esempio con help
). @MartijnPieters spiegato questo processo abbastanza bene in questa risposta .
Si può effettivamente ottenere la clinica argomento in pitone e di farlo in modo dinamico, ma io preferisco il modo manuale: Aggiunta della firma al docstring:
Nel tuo caso:
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.");
Ho fatto un uso pesante di questo nel mio pacchetto: iteration_utilities/src
. Quindi, per dimostrare che funziona io uso una delle funzioni C-estensione esposti da questo pacchetto:
>>> 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.
[...]
Il docstring per questa funzione è definita questo file .
E 'importante rendersi conto che questo non è possibile per python <3.4 ed è necessario seguire alcune regole:
-
È necessario includere
--\n\n
dopo la linea di definizione della firma. -
La firma deve essere in prima linea della docstring.
-
La firma deve essere valido, cioè
foo(a, b=1, c)
fallisce perché non è possibile definire argomenti posizionali dopo discussioni con default. -
È possibile fornire una sola firma. Così non funziona se si utilizza qualcosa come:
foo(a) foo(x, a, b) -- Narrative documentation