Manejo de excepciones
*********************

Las funciones descritas en este capítulo le permitirán manejar y
aumentar las excepciones de Python. Es importante comprender algunos
de los conceptos básicos del manejo de excepciones de Python. Funciona
de manera similar a la variable POSIX "errno": hay un indicador global
(por subproceso) del último error que ocurrió. La mayoría de las
funciones de C API no borran esto en caso de éxito, pero lo
configurarán para indicar la causa del error en caso de falla. La
mayoría de las funciones de C API también retornan un indicador de
error, generalmente "NULL" si se supone que retornan un puntero, o
"-1" si retornan un número entero (excepción: las funciones
"PyArg_*()" retornan "1" para el éxito y "0" para el fracaso).

Concretamente, el indicador de error consta de tres punteros de
objeto: el tipo de excepción, el valor de la excepción y el objeto de
rastreo. Cualquiera de esos punteros puede ser "NULL" si no está
configurado (aunque algunas combinaciones están prohibidas, por
ejemplo, no puede tener un rastreo no "NULL" si el tipo de excepción
es "NULL").

Cuando una función debe fallar porque alguna función que llamó falló,
generalmente no establece el indicador de error; la función que llamó
ya lo configuró. Es responsable de manejar el error y borrar la
excepción o regresar después de limpiar cualquier recurso que tenga
(como referencias de objetos o asignaciones de memoria); debería *no*
continuar normalmente si no está preparado para manejar el error. Si
regresa debido a un error, es importante indicarle a la persona que
llama que se ha establecido un error. Si el error no se maneja o se
propaga cuidadosamente, es posible que las llamadas adicionales a la
API de Python/C no se comporten como se espera y pueden fallar de
manera misteriosa.

Nota:

  El indicador de error es **no** el resultado de "sys.exc_info()". El
  primero corresponde a una excepción que aún no se detecta (y, por lo
  tanto, todavía se está propagando), mientras que el segundo retorna
  una excepción después de que se detecta (y, por lo tanto, ha dejado
  de propagarse).


Impresión y limpieza
====================

void PyErr_Clear()

   Borra el indicador de error. Si el indicador de error no está
   configurado, no hay efecto.

void PyErr_PrintEx(int set_sys_last_vars)

   Imprime un rastreo estándar en "sys.stderr" y borra el indicador de
   error. **A menos que** el error sea un "Salida del sistema", en ese
   caso no se imprime ningún rastreo y el proceso de Python se cerrará
   con el código de error especificado por la instancia de "Salida del
   sistema".

   Llame a esta función **solo** cuando el indicador de error está
   configurado. De lo contrario, provocará un error fatal!

   Si *set_sys_last_vars* no es cero, las variables "sys.last_type",
   "sys.last_value" y "sys.last_traceback" se establecerán en el tipo,
   valor y rastreo de la excepción impresa, respectivamente.

void PyErr_Print()

   Alias para "PyErr_PrintEx(1)".

void PyErr_WriteUnraisable(PyObject *obj)

   Llama "sys.unraisablehook()" utilizando la excepción actual y el
   argumento *obj*.

   Esta función de utilidad imprime un mensaje de advertencia en
   "sys.stderr" cuando se ha establecido una excepción, pero es
   imposible que el intérprete la active. Se usa, por ejemplo, cuando
   ocurre una excepción en un método "__del__()".

   La función se llama con un solo argumento *obj* que identifica el
   contexto en el que ocurrió la excepción que no se evalúa. Si es
   posible, la repr *obj* se imprimirá en el mensaje de advertencia.

   Se debe establecer una excepción al llamar a esta función.


Lanzando excepciones
====================

Estas funciones lo ayudan a configurar el indicador de error del hilo
actual. Por conveniencia, algunas de estas funciones siempre
retornarán un puntero "NULL" para usar en una declaración "return".

void PyErr_SetString(PyObject *type, const char *message)

   This is the most common way to set the error indicator.  The first
   argument specifies the exception type; it is normally one of the
   standard exceptions, e.g. "PyExc_RuntimeError".  You need not
   increment its reference count. The second argument is an error
   message; it is decoded from "'utf-8'".

void PyErr_SetObject(PyObject *type, PyObject *value)

   Esta función es similar a "PyErr_SetString()" pero le permite
   especificar un objeto Python arbitrario para el "valor" de la
   excepción.

PyObject* PyErr_Format(PyObject *exception, const char *format, ...)
    *Return value: Always NULL.*

   Esta función establece el indicador de error y retorna "NULL".
   *exception* debe ser una clase de excepción Python. El *format* y
   los parámetros posteriores ayudan a formatear el mensaje de error;
   tienen el mismo significado y valores que en
   "PyUnicode_FromFormat()". *format* es una cadena de caracteres
   codificada en ASCII.

PyObject* PyErr_FormatV(PyObject *exception, const char *format, va_list vargs)
    *Return value: Always NULL.*

   Igual que "PyErr_Format()", pero tomando un argumento "va_list" en
   lugar de un número variable de argumentos.

   Nuevo en la versión 3.5.

void PyErr_SetNone(PyObject *type)

   Esta es una abreviatura de "PyErr_SetObject(type, Py_None)".

int PyErr_BadArgument()

   Esta es una abreviatura de "PyErr_SetString(PyExc_TypeError,
   message)", donde *message* indica que se invocó una operación
   incorporada con un argumento ilegal. Es principalmente para uso
   interno.

PyObject* PyErr_NoMemory()
    *Return value: Always NULL.*

   Esta es una abreviatura de "PyErr_SetNone(PyExc_MemoryError)";
   retorna "NULL" para que una función de asignación de objetos pueda
   escribir "return PyErr_NoMemory();" cuando se queda sin memoria.

PyObject* PyErr_SetFromErrno(PyObject *type)
    *Return value: Always NULL.*

   Esta es una función conveniente para generar una excepción cuando
   una función de biblioteca C ha retornado un error y establece la
   variable C "errno". Construye un objeto tupla cuyo primer elemento
   es el valor entero "errno" y cuyo segundo elemento es el mensaje de
   error correspondiente (obtenido de "strerror()"), y luego llama a
   "PyErr_SetObject(type , objeto)". En Unix, cuando el valor "errno"
   es "EINTR", que indica una llamada interrumpida del sistema, esto
   llama "PyErr_CheckSignals()", y si eso establece el indicador de
   error, lo deja configurado a ese. La función siempre retorna
   "NULL", por lo que una función envolvente alrededor de una llamada
   del sistema puede escribir "return PyErr_SetFromErrno (type);"
   cuando la llamada del sistema retorna un error.

PyObject* PyErr_SetFromErrnoWithFilenameObject(PyObject *type, PyObject *filenameObject)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromErrno()", con el comportamiento adicional
   de que si *filenameObject * no es ``NULL``, se pasa al constructor
   de *type* como tercer parámetro. En el caso de la excepción
   "OSError", se utiliza para definir el atributo "filename" de la
   instancia de excepción.

PyObject* PyErr_SetFromErrnoWithFilenameObjects(PyObject *type, PyObject *filenameObject, PyObject *filenameObject2)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromErrnoWithFilenameObject()", pero toma un
   segundo objeto de nombre de archivo, para generar errores cuando
   falla una función que toma dos nombres de archivo.

   Nuevo en la versión 3.4.

PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromErrnoWithFilenameObject()", pero el nombre
   del archivo se da como una cadena de caracteres de C. *filename* se
   decodifica a partir de la codificación del sistema de archivos
   ("os.fsdecode()").

PyObject* PyErr_SetFromWindowsErr(int ierr)
    *Return value: Always NULL.*

   Esta es una función conveniente para subir "WindowsError". Si se
   llama con *ierr* de "0", el código de error retornado por una
   llamada a "GetLastError()" se usa en su lugar. Llama a la función
   Win32 "FormatMessage()" para recuperar la descripción de Windows
   del código de error proporcionado por *ierr* o "GetLastError()",
   luego construye un objeto de tupla cuyo primer elemento es el
   *ierr* valor y cuyo segundo elemento es el mensaje de error
   correspondiente (obtenido de "FormatMessage()"), y luego llama a
   "PyErr_SetObject(PyExc_WindowsError, object)". Esta función siempre
   retorna "NULL".

   Disponibilidad: Windows.

PyObject* PyErr_SetExcFromWindowsErr(PyObject *type, int ierr)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromWindowsErr()", con un parámetro adicional
   que especifica el tipo de excepción que se generará.

   Disponibilidad: Windows.

PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromWindowsErrWithFilenameObject()", pero el
   nombre del archivo se da como una cadena de caracteres de C.
   *filename* se decodifica a partir de la codificación del sistema de
   archivos ("os.fsdecode()").

   Disponibilidad: Windows.

PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromWindowsErrWithFilenameObject()", con un
   parámetro adicional que especifica el tipo de excepción que se
   generará.

   Disponibilidad: Windows.

PyObject* PyErr_SetExcFromWindowsErrWithFilenameObjects(PyObject *type, int ierr, PyObject *filename, PyObject *filename2)
    *Return value: Always NULL.*

   Similar a "PyErr_SetExcFromWindowsErrWithFilenameObject()", pero
   acepta un segundo objeto de nombre de archivo.

   Disponibilidad: Windows.

   Nuevo en la versión 3.4.

PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, const char *filename)
    *Return value: Always NULL.*

   Similar a "PyErr_SetFromWindowsErrWithFilename()", con un parámetro
   adicional que especifica el tipo de excepción que se generará.

   Disponibilidad: Windows.

PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
    *Return value: Always NULL.*

   Esta es una función conveniente para subir "ImportError". *msg* se
   establecerá como la cadena de mensaje de la excepción. *name* y
   *path*, que pueden ser "NULL", se establecerán como atributos
   respectivos "name" y "path" de "ImportError".

   Nuevo en la versión 3.3.

PyObject* PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, PyObject *name, PyObject *path)
    *Return value: Always NULL.*

   Al igual que "PyErr_SetImportError()" pero esta función permite
   especificar una subclase de "ImportError" para aumentar.

   Nuevo en la versión 3.6.

void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)

   Establece información de archivo, línea y desplazamiento para la
   excepción actual. Si la excepción actual no es un "SyntaxError",
   establece atributos adicionales, lo que hace que el sub sistema de
   impresión de excepciones piense que la excepción es "SyntaxError".

   Nuevo en la versión 3.4.

void PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)

   Como "PyErr_SyntaxLocationObject()", pero *filename* es una cadena
   de bytes decodificada a partir de la codificación del sistema de
   archivos ("os.fsdecode()").

   Nuevo en la versión 3.2.

void PyErr_SyntaxLocation(const char *filename, int lineno)

   Like "PyErr_SyntaxLocationEx()", but the *col_offset* parameter is
   omitted.

void PyErr_BadInternalCall()

   Esta es una abreviatura de "PyErr_SetString(PyExc_SystemError,
   message)", donde *message* indica que se invocó una operación
   interna (por ejemplo, una función de Python/C API) con un argumento
   ilegal. Es principalmente para uso interno.


Emitir advertencias
===================

Use estas funciones para emitir advertencias desde el código C.
Reflejan funciones similares exportadas por el módulo Python
"warnings". Normalmente imprimen un mensaje de advertencia a
*sys.stderr*; sin embargo, también es posible que el usuario haya
especificado que las advertencias se conviertan en errores, y en ese
caso generarán una excepción. También es posible que las funciones
generen una excepción debido a un problema con la maquinaria de
advertencia. El valor de retorno es "0" si no se genera una excepción,
o "-1" si se genera una excepción. (No es posible determinar si
realmente se imprime un mensaje de advertencia, ni cuál es el motivo
de la excepción; esto es intencional). Si se produce una excepción, la
persona que llama debe hacer su manejo normal de excepciones (por
ejemplo, referencias propiedad de "Py_DECREF()" y retornan un valor de
error).

int PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level)

   Emite un mensaje de advertencia. El argumento *category* es una
   categoría de advertencia (ver más abajo) o "NULL"; el argumento
   *message* es una cadena de caracteres codificada en UTF-8.
   *stack_level* es un número positivo que proporciona una cantidad de
   marcos de pila; la advertencia se emitirá desde la línea de código
   que se está ejecutando actualmente en ese marco de pila. Un
   *stack_level* de 1 es la función que llama "PyErr_WarnEx()", 2 es
   la función por encima de eso, y así sucesivamente.

   Las categorías de advertencia deben ser subclases de
   "PyExc_Warning"; "PyExc_Warning" es una subclase de
   "PyExc_Exception"; la categoría de advertencia predeterminada es
   "PyExc_RuntimeWarning". Las categorías de advertencia estándar de
   Python están disponibles como variables globales cuyos nombres se
   enumeran en Categorías de advertencia estándar.

   Para obtener información sobre el control de advertencia, consulte
   la documentación del módulo "warnings" y la opción "-W" en la
   documentación de la línea de comandos. No hay API de C para el
   control de advertencia.

int PyErr_WarnExplicitObject(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry)

   Issue a warning message with explicit control over all warning
   attributes.  This is a straightforward wrapper around the Python
   function "warnings.warn_explicit()"; see there for more
   information.  The *module* and *registry* arguments may be set to
   "NULL" to get the default effect described there.

   Nuevo en la versión 3.4.

int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)

   Similar a "PyErr_WarnExplicitObject()" excepto que *message* y
   *module* son cadenas codificadas UTF-8, y *filename* se decodifica
   de la codificación del sistema de archivos ("os.fsdecode()").

int PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, const char *format, ...)

   Función similar a "PyErr_WarnEx()", pero usa
   "PyUnicode_FromFormat()" para formatear el mensaje de advertencia.
   *format* es una cadena de caracteres codificada en ASCII.

   Nuevo en la versión 3.2.

int PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level, const char *format, ...)

   Función similar a "PyErr_WarnFormat()", pero *category* es
   "ResourceWarning" y pasa *source* a "warnings.WarningMessage()".

   Nuevo en la versión 3.6.


Consultando el indicador de error
=================================

PyObject* PyErr_Occurred()
    *Return value: Borrowed reference.*

   Prueba si el indicador de error está configurado. Si se establece,
   retorna la excepción *type* (el primer argumento de la última
   llamada a una de las funciones "PyErr_Set*()" o "PyErr_Restore()").
   Si no está configurado, retorna "NULL". No posee una referencia al
   valor de retorno, por lo que no necesita usar "Py_DECREF()".

   La persona que llama debe retener el GIL.

   Nota:

     No compare el valor de retorno con una excepción específica; use
     "PyErr_ExceptionMatches()" en su lugar, como se muestra a
     continuación. (La comparación podría fallar fácilmente ya que la
     excepción puede ser una instancia en lugar de una clase, en el
     caso de una excepción de clase, o puede ser una subclase de la
     excepción esperada).

int PyErr_ExceptionMatches(PyObject *exc)

   Equivalente a "PyErr_GivenExceptionMatches(PyErr_Occurred(), exc)".
   Esto solo debería llamarse cuando se establece una excepción; se
   producirá una infracción de acceso a la memoria si no se ha
   producido ninguna excepción.

int PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc)

   Retorna verdadero si la excepción *dada* coincide con el tipo de
   excepción en *exc*. Si *exc* es un objeto de clase, esto también
   retorna verdadero cuando *dado* es una instancia de una subclase.
   Si *exc* es una tupla, se busca una coincidencia en todos los tipos
   de excepción en la tupla (y recursivamente en sub tuplas).

void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)

   Recupere el indicador de error en tres variables cuyas direcciones
   se pasan. Si el indicador de error no está configurado, configure
   las tres variables en "NULL". Si está configurado, se borrará y
   usted tendrá una referencia a cada objeto recuperado. El objeto de
   valor y rastreo puede ser "NULL" incluso cuando el objeto de tipo
   no lo es.

   Nota:

     Normalmente, esta función solo la usa el código que necesita
     capturar excepciones o el código que necesita guardar y restaurar
     el indicador de error temporalmente, por ejemplo:

        {
           PyObject *type, *value, *traceback;
           PyErr_Fetch(&type, &value, &traceback);

           /* ... code that might produce other errors ... */

           PyErr_Restore(type, value, traceback);
        }

void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)

   Establece el indicador de error de los tres objetos. Si el
   indicador de error ya está configurado, se borra primero. Si los
   objetos son "NULL", el indicador de error se borra. No pase un tipo
   "NULL" y un valor o rastreo no "NULL". El tipo de excepción debería
   ser una clase. No pase un tipo o valor de excepción no válido.
   (Violar estas reglas causará problemas sutiles más adelante). Esta
   llamada quita una referencia a cada objeto: debe tener una
   referencia a cada objeto antes de la llamada y después de la
   llamada ya no posee estas referencias. (Si no comprende esto, no
   use esta función. Se lo advertí).

   Nota:

     Normalmente, esta función solo la usa el código que necesita
     guardar y restaurar el indicador de error temporalmente. Use
     "PyErr_Fetch()" para guardar el indicador de error actual.

void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)

   Bajo ciertas circunstancias, los valores retornados por
   "PyErr_Fetch()" a continuación pueden ser "no normalizados", lo que
   significa que "*exc" es un objeto de clase pero "*val" no es una
   instancia de la misma clase . Esta función se puede utilizar para
   crear instancias de la clase en ese caso. Si los valores ya están
   normalizados, no pasa nada. La normalización retrasada se
   implementa para mejorar el rendimiento.

   Nota:

     Esta función *no* establece implícitamente el atributo
     "__traceback__" en el valor de excepción. Si se desea establecer
     el rastreo de manera adecuada, se necesita el siguiente fragmento
     adicional:

        if (tb != NULL) {
          PyException_SetTraceback(val, tb);
        }

void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)

   Recupere la información de excepción, como se conoce de
   "sys.exc_info()". Esto se refiere a una excepción que *ya fue
   capturada*, no a una excepción que se planteó recientemente.
   Retorna nuevas referencias para los tres objetos, cualquiera de los
   cuales puede ser "NULL". No modifica el estado de información de
   excepción.

   Nota:

     Esta función normalmente no es utilizada por el código que quiere
     manejar excepciones. En cambio, se puede usar cuando el código
     necesita guardar y restaurar el estado de excepción
     temporalmente. Use "PyErr_SetExcInfo()" para restaurar o borrar
     el estado de excepción.

   Nuevo en la versión 3.3.

void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)

   Establezca la información de excepción, como se conoce de
   "sys.exc_info()". Esto se refiere a una excepción que *ya fue
   capturada*, no a una excepción que se planteó recientemente. Esta
   función roba las referencias de los argumentos. Para borrar el
   estado de excepción, pase "NULL" para los tres argumentos. Para ver
   las reglas generales sobre los tres argumentos, consulte
   "PyErr_Restore()".

   Nota:

     Esta función normalmente no es utilizada por el código que quiere
     manejar excepciones. En cambio, se puede usar cuando el código
     necesita guardar y restaurar el estado de excepción
     temporalmente. Use "PyErr_GetExcInfo()" para leer el estado de
     excepción.

   Nuevo en la versión 3.3.


Manejo de señal
===============

int PyErr_CheckSignals()

   Esta función interactúa con el manejo de la señal de Python.
   Comprueba si se ha enviado una señal a los procesos y, de ser así,
   invoca el controlador de señal correspondiente. Si el módulo
   "signal" es compatible, esto puede invocar un controlador de señal
   escrito en Python. En todos los casos, el efecto predeterminado
   para "SIGINT" es aumentar la excepción "KeyboardInterrupt". Si se
   produce una excepción, se establece el indicador de error y la
   función retorna "-1"; de lo contrario, la función retorna "0". El
   indicador de error puede o no borrarse si se configuró previamente.

void PyErr_SetInterrupt()

   Simule el efecto de la llegada de una señal "SIGINT". La próxima
   vez se llama "PyErr_CheckSignals()", se llamará al manejador de
   señal de Python para "SIGINT".

   Si "SIGINT" no es manejado por Python (se configuró en
   "signal.SIG_DFL" o "signal.SIG_IGN"), esta función no hace nada.

int PySignal_SetWakeupFd(int fd)

   Esta función de utilidad especifica un descriptor de archivo en el
   que el número de señal se escribe como un solo byte cada vez que se
   recibe una señal. *fd* debe ser sin bloqueo. retorna el descriptor
   de archivo anterior.

   El valor "-1" desactiva la función; Este es el estado inicial. Esto
   es equivalente a "signal.set_wakeup_fd()" en Python, pero sin
   verificación de errores. *fd* debe ser un descriptor de archivo
   válido. La función solo debe llamarse desde el hilo principal.

   Distinto en la versión 3.5: En Windows, la función ahora también
   admite controladores de socket.


Clases de Excepción
===================

PyObject* PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
    *Return value: New reference.*

   Esta función de utilidad crea y retorna una nueva clase de
   excepción. El argumento *name* debe ser el nombre de la nueva
   excepción, una cadena de caracteres en C de la forma
   "module.classname". Los argumentos *base* y *dict* son normalmente
   "NULL". Esto crea un objeto de clase derivado de "Exception"
   (accesible en C como "PyExc_Exception").

   El atributo "__module__" de la nueva clase se establece en la
   primera parte (hasta el último punto) del argumento *name*, y el
   nombre de la clase se establece en la última parte (después del
   último punto). El argumento *base* se puede usar para especificar
   clases base alternativas; puede ser solo una clase o una tupla de
   clases. El argumento *dict* se puede usar para especificar un
   diccionario de variables de clase y métodos.

PyObject* PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict)
    *Return value: New reference.*

   Igual que "PyErr_NewException()", excepto que la nueva clase de
   excepción puede recibir fácilmente una cadena de documentación: si
   *doc* no es "NULL", se utilizará como la cadena de documentación
   para la clase de excepción.

   Nuevo en la versión 3.2.


Objetos Excepción
=================

PyObject* PyException_GetTraceback(PyObject *ex)
    *Return value: New reference.*

   Retorna el rastreo asociado con la excepción como una nueva
   referencia, accesible desde Python a través de "__traceback__". Si
   no hay un rastreo asociado, esto retorna "NULL".

int PyException_SetTraceback(PyObject *ex, PyObject *tb)

   Establezca el rastreo asociado con la excepción a *tb*. Use
   "Py_None" para borrarlo.

PyObject* PyException_GetContext(PyObject *ex)
    *Return value: New reference.*

   Retorna el contexto (otra instancia de excepción durante cuyo
   manejo *ex* se generó) asociado con la excepción como una nueva
   referencia, accesible desde Python a través de "__context__". Si no
   hay un contexto asociado, esto retorna "NULL".

void PyException_SetContext(PyObject *ex, PyObject *ctx)

   Establece el contexto asociado con la excepción a *ctx*. Use "NULL"
   para borrarlo. No hay verificación de tipo para asegurarse de que
   *ctx* es una instancia de excepción. Esto roba una referencia a
   *ctx*.

PyObject* PyException_GetCause(PyObject *ex)
    *Return value: New reference.*

   Retorna la causa (ya sea una instancia de excepción, o "None",
   establecida por "raise ... from ...") asociada con la excepción
   como una nueva referencia, como accesible desde Python a través de
   "__causa__".

void PyException_SetCause(PyObject *ex, PyObject *cause)

   Establece la causa asociada con la excepción a *cause*. Use "NULL"
   para borrarlo. No hay verificación de tipo para asegurarse de que
   *cause* sea una instancia de excepción o "None". Esto roba una
   referencia a *cause*.

   "__suppress_context__" es implícitamente establecido en "True" por
   esta función.


Objectos Unicode de Excepción
=============================

Las siguientes funciones se utilizan para crear y modificar
excepciones Unicode de C.

PyObject* PyUnicodeDecodeError_Create(const char *encoding, const char *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)
    *Return value: New reference.*

   Crea un objeto "UnicodeDecodeError" con los atributos *encoding*,
   *object*, *length*, *start*, *end* y *reason*. *encoding* y
   *reason* son cadenas codificadas UTF-8.

PyObject* PyUnicodeEncodeError_Create(const char *encoding, const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)
    *Return value: New reference.*

   Crea un objeto "UnicodeEncodeError" con los atributos *encoding*,
   *object*, *length*, *start*, *end* y *reason*. *encoding* y
   *reason* son cadenas codificadas UTF-8.

   Obsoleto desde la versión 3.3: 3.11"Py_UNICODE" está obsoleto desde
   Python 3.3. Migre por favor a
   "PyObject_CallFunction(PyExc_UnicodeEncodeError, "sOnns", ...)".

PyObject* PyUnicodeTranslateError_Create(const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)
    *Return value: New reference.*

   Crea un objeto "UnicodeTranslateError" con los atributos
   *encoding*, *object*, *length*, *start*, *end* y *reason*.
   *encoding* y *reason* son cadenas codificadas UTF-8.

   Obsoleto desde la versión 3.3: 3.11"Py_UNICODE" está obsoleto desde
   Python 3.3. Migre por favor a
   "PyObject_CallFunction(PyExc_UnicodeTranslateError, "sOnns", ...)".

PyObject* PyUnicodeDecodeError_GetEncoding(PyObject *exc)
PyObject* PyUnicodeEncodeError_GetEncoding(PyObject *exc)
    *Return value: New reference.*

   Retorna el atributo *encoding* del objeto de excepción dado.

PyObject* PyUnicodeDecodeError_GetObject(PyObject *exc)
PyObject* PyUnicodeEncodeError_GetObject(PyObject *exc)
PyObject* PyUnicodeTranslateError_GetObject(PyObject *exc)
    *Return value: New reference.*

   Retorna el atributo *object* del objeto de excepción dado.

int PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)
int PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)
int PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)

   Obtiene el atributo *start* del objeto de excepción dado y lo
   coloca en **start*. *start* no debe ser "NULL". retorna "0" en caso
   de éxito, "-1" en caso de error.

int PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)
int PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)
int PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)

   Establece el atributo *start* del objeto de excepción dado en
   *start*. Retorna "0" en caso de éxito, "-1" en caso de error.

int PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
int PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
int PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *end)

   Obtiene el atributo *end* del objeto de excepción dado y lo coloca
   en **end*. *end* no debe ser "NULL". retorna "0" en caso de éxito,
   "-1" en caso de error.

int PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)
int PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)
int PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)

   Establece el atributo *end* del objeto de excepción dado en *end*.
   Retorna "0" en caso de éxito, "-1" en caso de error.

PyObject* PyUnicodeDecodeError_GetReason(PyObject *exc)
PyObject* PyUnicodeEncodeError_GetReason(PyObject *exc)
PyObject* PyUnicodeTranslateError_GetReason(PyObject *exc)
    *Return value: New reference.*

   Retorna el atributo *reason* del objeto de excepción dado.

int PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)
int PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)
int PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)

   Establece el atributo *reason* del objeto de excepción dado en
   *reason*. Retorna "0" en caso de éxito, "-1" en caso de error.


Control de Recursión
====================

Estas dos funciones proporcionan una forma de realizar llamadas
recursivas seguras en el nivel C, tanto en el núcleo como en los
módulos de extensión. Son necesarios si el código recursivo no invoca
necesariamente el código Python (que rastrea su profundidad de
recursión automáticamente). Tampoco son necesarios para las
implementaciones de *tp_call* porque call protocol se encarga del
manejo de la recursividad.

int Py_EnterRecursiveCall(const char *where)

   Marca un punto donde una llamada recursiva de nivel C está a punto
   de realizarse.

   Si "USE_STACKCHECK" está definido, esta función verifica si la pila
   del SO se desbordó usando "PyOS_CheckStack()". En este caso,
   establece un "MemoryError" y retorna un valor distinto de cero.

   La función verifica si se alcanza el límite de recursión. Si este
   es el caso, se establece a "RecursionError" y se retorna un valor
   distinto de cero. De lo contrario, se retorna cero.

   *where* debería ser una cadena de caracteres codificada en UTF-8
   como ""en la comprobación de instancia"" para concatenarse con el
   mensaje "RecursionError" causado por el límite de profundidad de
   recursión.

   Distinto en la versión 3.9: Esta función ahora también está
   disponible en la API limitada.

void Py_LeaveRecursiveCall(void)

   Termina una "Py_EnterRecursiveCall()". Se debe llamar una vez por
   cada invocación *exitosa* de "Py_EnterRecursiveCall()".

   Distinto en la versión 3.9: Esta función ahora también está
   disponible en la API limitada.

La implementación adecuada de "tp_repr" para los tipos de contenedor
requiere un manejo de recursión especial. Además de proteger la pila,
"tp_repr" también necesita rastrear objetos para evitar ciclos. Las
siguientes dos funciones facilitan esta funcionalidad. Efectivamente,
estos son los C equivalentes a "reprlib.recursive_repr()".

int Py_ReprEnter(PyObject *object)

   Llamado al comienzo de la implementación "tp_repr" para detectar
   ciclos.

   Si el objeto ya ha sido procesado, la función retorna un entero
   positivo. En ese caso, la implementación "tp_repr" debería retornar
   un objeto de cadena que indique un ciclo. Como ejemplos, los
   objetos "dict" retornan "{...}" y los objetos "list" retornan
   "[...]".

   La función retornará un entero negativo si se alcanza el límite de
   recursión. En ese caso, la implementación "tp_repr" normalmente
   debería retornar "NULL".

   De lo contrario, la función retorna cero y la implementación
   "tp_repr" puede continuar normalmente.

void Py_ReprLeave(PyObject *object)

   Termina a "Py_ReprEnter()". Se debe llamar una vez por cada
   invocación de "Py_ReprEnter()" que retorna cero.


Excepciones Estándar
====================

Todas las excepciones estándar de Python están disponibles como
variables globales cuyos nombres son "PyExc_" seguidos del nombre de
excepción de Python. Estos tienen el tipo "PyObject*"; todos son
objetos de clase. Para completar, aquí están todas las variables:

+-------------------------------------------+-----------------------------------+------------+
| Nombre en C                               | Nombre en Python                  | Notas      |
|===========================================|===================================|============|
| "PyExc_BaseException"                     | "BaseException"                   | [1]        |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_Exception"                         | "Exception"                       | [1]        |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ArithmeticError"                   | "ArithmeticError"                 | [1]        |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_AssertionError"                    | "AssertionError"                  |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_AttributeError"                    | "AttributeError"                  |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_BlockingIOError"                   | "BlockingIOError"                 |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_BrokenPipeError"                   | "BrokenPipeError"                 |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_BufferError"                       | "BufferError"                     |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ChildProcessError"                 | "ChildProcessError"               |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ConnectionAbortedError"            | "ConnectionAbortedError"          |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ConnectionError"                   | "ConnectionError"                 |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ConnectionRefusedError"            | "ConnectionRefusedError"          |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ConnectionResetError"              | "ConnectionResetError"            |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_EOFError"                          | "EOFError"                        |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_FileExistsError"                   | "FileExistsError"                 |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_FileNotFoundError"                 | "FileNotFoundError"               |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_FloatingPointError"                | "FloatingPointError"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_GeneratorExit"                     | "GeneratorExit"                   |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ImportError"                       | "ImportError"                     |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_IndentationError"                  | "IndentationError"                |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_IndexError"                        | "IndexError"                      |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_InterruptedError"                  | "InterruptedError"                |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_IsADirectoryError"                 | "IsADirectoryError"               |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_KeyError"                          | "KeyError"                        |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_KeyboardInterrupt"                 | "KeyboardInterrupt"               |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_LookupError"                       | "LookupError"                     | [1]        |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_MemoryError"                       | "MemoryError"                     |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ModuleNotFoundError"               | "ModuleNotFoundError"             |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_NameError"                         | "NameError"                       |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_NotADirectoryError"                | "NotADirectoryError"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_NotImplementedError"               | "NotImplementedError"             |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_OSError"                           | "OSError"                         | [1]        |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_OverflowError"                     | "OverflowError"                   |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_PermissionError"                   | "PermissionError"                 |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ProcessLookupError"                | "ProcessLookupError"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_RecursionError"                    | "RecursionError"                  |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ReferenceError"                    | "ReferenceError"                  |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_RuntimeError"                      | "RuntimeError"                    |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_StopAsyncIteration"                | "StopAsyncIteration"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_StopIteration"                     | "StopIteration"                   |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_SyntaxError"                       | "SyntaxError"                     |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_SystemError"                       | "SystemError"                     |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_SystemExit"                        | "SystemExit"                      |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_TabError"                          | "TabError"                        |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_TimeoutError"                      | "TimeoutError"                    |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_TypeError"                         | "TypeError"                       |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_UnboundLocalError"                 | "UnboundLocalError"               |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_UnicodeDecodeError"                | "UnicodeDecodeError"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_UnicodeEncodeError"                | "UnicodeEncodeError"              |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_UnicodeError"                      | "UnicodeError"                    |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_UnicodeTranslateError"             | "UnicodeTranslateError"           |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ValueError"                        | "ValueError"                      |            |
+-------------------------------------------+-----------------------------------+------------+
| "PyExc_ZeroDivisionError"                 | "ZeroDivisionError"               |            |
+-------------------------------------------+-----------------------------------+------------+

Nuevo en la versión 3.3: "PyExc_BlockingIOError",
"PyExc_BrokenPipeError", "PyExc_ChildProcessError",
"PyExc_ConnectionError", "PyExc_ConnectionAbortedError",
"PyExc_ConnectionRefusedError", "PyExc_ConnectionResetError",
"PyExc_FileExistsError", "PyExc_FileNotFoundError",
"PyExc_InterruptedError", "PyExc_IsADirectoryError",
"PyExc_NotADirectoryError", "PyExc_PermissionError",
"PyExc_ProcessLookupError" y "PyExc_TimeoutError" fueron introducidos
luego de **PEP 3151**.

Nuevo en la versión 3.5: "PyExc_StopAsyncIteration" y
"PyExc_RecursionError".

Nuevo en la versión 3.6: "PyExc_ModuleNotFoundError".

Estos son alias de compatibilidad para "PyExc_OSError":

+---------------------------------------+------------+
| Nombre en C                           | Notas      |
|=======================================|============|
| "PyExc_EnvironmentError"              |            |
+---------------------------------------+------------+
| "PyExc_IOError"                       |            |
+---------------------------------------+------------+
| "PyExc_WindowsError"                  | [2]        |
+---------------------------------------+------------+

Distinto en la versión 3.3: Estos alias solían ser tipos de excepción
separados.

Notas:

[1] Esta es una clase base para otras excepciones estándar.

[2] Solo se define en Windows; proteja el código que usa esto probando
    que la macro del preprocesador "MS_WINDOWS" está definida.


Categorías de advertencia estándar
==================================

Todas las categorías de advertencia estándar de Python están
disponibles como variables globales cuyos nombres son "PyExc_"
seguidos del nombre de excepción de Python. Estos tienen el tipo
"PyObject*"; todos son objetos de clase. Para completar, aquí están
todas las variables:

+--------------------------------------------+-----------------------------------+------------+
| Nombre en C                                | Nombre en Python                  | Notas      |
|============================================|===================================|============|
| "PyExc_Warning"                            | "Warning"                         | [3]        |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_BytesWarning"                       | "BytesWarning"                    |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_DeprecationWarning"                 | "DeprecationWarning"              |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_FutureWarning"                      | "FutureWarning"                   |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_ImportWarning"                      | "ImportWarning"                   |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_PendingDeprecationWarning"          | "PendingDeprecationWarning"       |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_ResourceWarning"                    | "ResourceWarning"                 |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_RuntimeWarning"                     | "RuntimeWarning"                  |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_SyntaxWarning"                      | "SyntaxWarning"                   |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_UnicodeWarning"                     | "UnicodeWarning"                  |            |
+--------------------------------------------+-----------------------------------+------------+
| "PyExc_UserWarning"                        | "UserWarning"                     |            |
+--------------------------------------------+-----------------------------------+------------+

Nuevo en la versión 3.2: "PyExc_ResourceWarning".

Notas:

[3] Esta es una clase base para otras categorías de advertencia
    estándar.
