1.7 Cadenas de formato para PyArg_ParseTuple()
La función PyArg_ParseTuple() se declara así:
int PyArg_ParseTuple(PyObject *arg, char *format, ...);
El argumento arg debe ser un objeto tupla que contenga una
lista de argumentos pasada de Python a una función C. El argumento
format debe ser una cadena de formato, cuya sintaxis se explica
más adelante. El resto de los argumentos deben ser direcciones de variables
cuyo tipo queda determinado por la cadena de formato. Para que tenga
éxito la conversión, el objeto arg debe concordar con el formato
y utilizarlo por completo.
Aunque PyArg_ParseTuple() comprueba que los argumentos de
Python tienen los tipos indicados, no puede comprobar la validez de las
direcciones de las variables de C que se pasen a la llamada: si se cometen
errores en este punto, el código efectuará operaciones no válidas o, al menos,
sobreescribirá porciones aleatorias de la memoria. ¡Hay que tener cuidado!
Una cadena de formato consta de cero o más ``unidades de formato''.
Una unidad de formato describe un objeto Python. Suele ser un solo
carácter o una secuencia de unidades de formato entre paréntesis. Salvo
algunas excepciones, una unidad de formato que no es una secuencia entre
paréntesis corresponde a un solo argumento de dirección para
PyArg_ParseTuple(). En la siguiente descripción,
la forma entrecomillada es la unidad de formato, la entrada entre paréntesis
es el tipo de objeto Python que concuerda con la unidad de formato
y la entrada entre corchetes es el tipo de la/s variable/s C cuyas direcciones
se han de pasar (se debe usar el operador "&" para pasar
la dirección de una variable).
Todas las referencias a objetos de Python proporcionadas al llamante
son referencias prestadas; no se debe decrementar su saldo
de referencias.
- "s" (cadena u objeto Unicode) [char *]
- Convierte una cadena u objeto Unicode de Python a puntero a
cadena de caracteres de C. No hay que proporcionar almacenamiento
a la propia cadena, ya que se guarda un puntero a una cadena existente
en la variable puntero a carácter cuya dirección se pasa. La cadena C
está terminada por nulo. La cadena de Python no debe contener
bytes nulos, en caso contrario, se lanza una excepción
TypeError. Los objetos Unicode se convierten a
cadenas de C utilizando la codificación predeterminada. Si falla la conversión,
se lanza una excepción UnicodeError.
- "s#" (objeto cadena, Unicode o cualquier objeto legible con read)
[char *, int]
- Esta variación sobre "s" almacena en dos variables de C, la primera un
puntero a una cadena de caracteres y la segunda su longitud. En este caso,
la cadena Python puede contener bytes cero en medio. Los objetos Unicode
devuelven un puntero a la versión codificada por defecto de la cadena si tal
conversión es posible. Los demás objetos legibles devuelven una referencia a
la representación de los datos internos en crudo.
- "z" (cadena o
None
) [char *]
- Como "s", pero el objeto Python puede ser también
None
,
en cuyo caso el puntero C se pone a NULL.
- "z#" (cadena o
None
o cualquier objeto legible con read)
[char *, int]
- Esto es a "s#" lo que "z" es a "s".
- "u" (objeto Unicode) [Py_UNICODE *]
- Convierte un objeto Unicode de Python a un puntero C que apunta a una
cadena terminada en nulo de datos Unicode (UTF-16). Como con
"s", no es necesario proporcionar espacio para la cadena de datos
Unicode, se guarda un puntero a los datos Unicode existentes en la variable
puntero Py_UNICODE cuya dirección se pasa.
- "u#" (objeto Unicode) [Py_UNICODE *, int]
- Esta variación sobre "u" almacena en dos variables de C,
la primera un puntero a una cadena de datos Unicode y la segunda su longitud.
- "es" (objeto cadena, Unicode o cualquier objeto legible con
read) [const char *encoding, char **buffer]
- Esta variación sobre "s" se usa para codificar objetos Unicode y
objetos convertibles en Unicode en una cadena de caracteres. Sólo funciona
para datos codificados sin caracteres NULL en medio.
Lee una variable de C y almacena en dos. La variable leída es un puntero a una cadena
de nombre de codificación (encoding). La primera variable destino es un puntero
a un puntero a una cadena (**buffer, utilizada para almacenar
los datos codificados y la otra un puntero a un entero (*buffer_length,
la longitud de la cadena).
El nombre de la codificación debe ser uno de los códec registrados. De ser
NULL, se utilizará la codificación predeterminada.
PyArg_ParseTuple() reservará un bloque del tamaño adecuado
mediante PyMem_NEW(), copiará los datos codificados a
este bloque y ajustará *buffer para que apunte al nuevo almacenamiento.
El que llama es responsable de llamar a PyMem_Free()
para liberar el bloque reservado tras su uso.
- "es#" (cadena, objeto Unicode o cualquier objeto legible con
read) [const char *encoding, char **buffer, int *buffer_length]
- Esta variación sobre "s#" se utiliza para codificar objetos Unicode y
compatibles a cadena de caracteres. Lee de una variable de C y almacena en
dos. La variable leída es un puntero a una cadena de nombre de codificación
(encoding), la primera escrita es un puntero a un puntero a una cadena de
caracteres (**buffer, que se utiliza para almacenar los datos codificados
y la última un puntero a un entero *buffer_length, la longitud de la cadena.
El nombre de la codificación debe ser uno de los códec registrados. De ser
NULL, se utilizará la codificación predeterminada.
Hay dos modos de funcionamiento:
Si *buffer apunta a un puntero NULL,
PyArg_ParseTuple() reservará un bloque del tamaño necesario
con PyMem_NEW(), copiará los datos codificados a este
bloque y ajustará *buffer para que haga referencia al almacenamiento
recién reservado. El que llama a esta función es responsable de llamara a
PyMem_Free() para liberar el bloque reservado, tras su uso.
Si *buffer apunta a un puntero no NULL (un bloque ya reservado),
PyArg_ParseTuple() utilizará esta ubicación e interpretará
que *buffer_length es el tamaño del bloque utilizable. Entonces, copiará
los datos codificados al bloque y les dará una terminación cero. Se señala
el desbordamiento del bloque mediante una excepción.
En los dos casos, se actualiza *buffer_length a la longitud de los datos
codificados, excluyendo el byte cero final.
- "b" (integer) [char]
- Convierte un entero de Python a un entero pequeño, almacenado en un
char de C.
- "h" (integer) [short int]
- Convierte un entero de Python a un short int de C.
- "i" (integer) [int]
- Convierte un entero de Python a un int de C.
- "l" (integer) [long int]
- Convierte un entero de Python a un long int de C.
- "c" (string of length 1) [char]
- Convierte un carácter de Python, es decir, una cadena de caracteres de
longitud uno, a un char de C.
- "f" (float) [float]
- Convierte un número de coma flotante de Python a un float de C.
- "d" (float) [double]
- Convierte un número de coma flotante de Python a un double de C.
- "D" (complex) [Py_complex]
- Convierte un número complejo de Python a una estructura Py_complex
de C.
- "O" (objeto) [PyObject *]
- Almacena un objeto de Python (sin conversión ninguna) a un puntero a
objeto de C. El programa de C recibe el objeto real traspasado. No se incrementa
el saldo de referencias del puntero. El puntero almacenado no es
NULL.
- "O!" (objeto) [typeobject, PyObject *]
- Almacena un objeto de Python en un puntero a objeto de C. Se parece a
"O", pero toma dos argumentos: el primero es la dirección de un objeto
tipo de Python, el segundo es la dirección de la variable C (de tipo
PyObject *) en la que se almacena el puntero a objeto. Si
el objeto de Python no tiene el tipo exigido, se lanza
TypeError.
- "O&" (objeto) [conversión, anything]
- Convierte un objeto de Python a una variable C mediante una función
converter de conversión, que debe tomar dos argumentos:
el primero es una función, el segundo es la dirección de una variable C
(de tipo arbitrario), convertida a void *.
Se invoca la función converter de este modo:
status =
conversión(
objeto, dirección);
donde objeto es el objeto de Python a convertir y
dirección es el argumento void * pasado a
PyArg_ConvertTuple(). El estado devuelto debería ser
1
para la conversión con éxito 0
si fracasó la conversión.
Si la conversión falla, la función conversión debería lanzar una excepción.
- "S" (cadena) [PyStringObject *]
- Como "O", pero necesita que el objeto Python sea un objeto cadena.
Lanza TypeError si no lo es. También se puede declarar la variable de C
como PyObject *.
- "U" (cadena Unicode) [PyUnicodeObject *]
- Como "O", pero necesita que el objeto Python sea un objeto Unicode.
Lanza TypeError si no lo es. También se puede declarar la variable de C
como PyObject *.
- "t#" (bloque de caracteres de sólo lectura) [char *, int]
- Como "s#", pero acepta la interfaz de sólo lectura mediante read.
La variable char * se hace apuntar al primer byte del bloque y
se asigna al int la longitud del bloque. Sólo se aceptan bloques de
un sólo segmento, se lanza TypeError en otros casos.
- "w" (bloque de caracteres de lectura/escritura) [char *]
- Como "s", pero acepta la interfaz de lectura-escritura mediante read/write.
El que llama a la función debe determinar la longitud del bloque por otros
medios, o usar "w#" en lugar de ésta.
Sólo se aceptan bloques de
un sólo segmento, se lanza TypeError en otros casos.
- "w#" (bloque de caracteres de lectura/escritura) [char *, int]
- Como "s#", pero acepta la interfaz de lectura-escritura mediante read/write.
La variable char * se hace apuntar al primer byte del bloque y
se asigna al int la longitud del bloque. Sólo se aceptan bloques de
un sólo segmento, se lanza TypeError en otros casos.
- "(elementos)" (tupla) [mismo nº elementos]
- El objeto debe se una secuencia de Python cuya longitud es el número
de unidades de formato de elementos. Los argumentos C deben corresponder
con las unidades de formato individuales de elementos. Se puede anidar
las unidades de formato.
Nota: En las versiones de Python anteriores a 1.5.2, este especificador
de formato sólo aceptaba una tupla que contenía los parámetros individuales, no
una secuencia arbitraria. El código que lanzara anteriormente
TypeError puede proseguir ahora sin lanzar excepciones.
No se espera que esto sea un problema para el código existente.
Es posible pasar enteros largos de Python cuando se requieran enteros.
Sin embargo, no se hace una verificación de rangos, truncándose los
bits más significativos silenciosamente si el campo receptor es demasiado
pequeño para recibir el valor (en realidad, la semántica se hereda de las
conversiones de C, por lo que puede ocurrir cualquier cosa).
Hay otros caracteres que tienen significado dentro de una cadena de
formato. No pueden darse dentro de paréntesis anidados. Son:
- "|"
- Indica que el resto de los argumentos de la lista de argumentos de Python
es opcional. Las variable de C correspondientes a los argumentos opcionales
deberían inicializarse a su valor por omisión. Cuando no se da valor a un
argumento opcional, PyArg_ParseTuple() no toca el contenido de
las variables C correspondientes.
- ":"
- La lista de unidades de formato termina aquí: la cadena que sigue a los dos puntos
se utiliza como nombre de la función en mensajes de error (el ``valor
asociado'' de la excepción que lanza PyArg_ParseTuple()).
- ";"
- La lista de unidades de formato termina aquí: la cadena que sigue a los dos puntos
se usa como mensaje de error en lugar del mensaje de error predeterminado.
Obviamente, ":" y ";" son mutuamente excluyentes.
Llamadas de ejemplo:
int vale;
int i, j;
long k, l;
char *s;
int tamanho;
vale = PyArg_ParseTuple(args, ""); /* Sin argumentos */
/* Llamada desde Python: f() */
vale = PyArg_ParseTuple(args, "s", &s); /* Una cadena */
/* Posible llamada desde Python: f('¡ahí va!') */
vale = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Dos enteros y una cadena */
/* Posible llamada desde Python: f(1, 2, 'tres') */
vale = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &tamanho);
/* Dos enteros y una cadena, cuyo tamaño se devuelve también */
/* Posible llamada desde Python: f(1, 2, 'tres') */
{
char *fichero;
char *modo = "r";
int tamanhobloque = 0;
ok = PyArg_ParseTuple(args, "s|si", &fichero, &modo, &tamanhobloque);
/* Una cadena y, opcionalmente, otra cadena y un entero */
/* Posibles llamadas desde Python:
f('spam')
f('spam', 'w')
f('spam', 'wb', 100000) */
}
{
int izquierda, tope, derecha, base, h, v;
ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
&izquierda, &tope, &derecha, &base, &h, &v);
/* Un rectángulo y un punto */
/* Posible llamada desde Python:
f(((0, 0), (400, 300)), (10, 10)) */
}
{
Py_complex c;
ok = PyArg_ParseTuple(args, "D:mifuncion", &c);
/* un complejo, más un nombre de función para los errores */
/* Posible llamada desde Python: mifuncion(1+2j) */
}
Ver Sobre este documento... para obtener información sobre sugerencias.