errno en Python: errores del sistema

Publicado el: 24/08/2026
Tempo de leitura: 4 minutos
Creative concept showing the word 'error' with cut out letters on a table with scissors and paper.

El módulo errno expone nombres simbólicos para códigos de error del sistema operativo usados por archivos, procesos, sockets, dispositivos y llamadas nativas. En vez de comparar números sin contexto como 2, 13 o 111, el código puede usar ENOENT, EACCES y ECONNREFUSED.

Python moderno convierte muchos códigos en subclases específicas de OSError, como FileNotFoundError, PermissionError, BlockingIOError y ConnectionRefusedError. Aun así, errno sigue siendo importante en integración nativa, I/O no bloqueante y manejo portable de condiciones menos comunes.

Por qué usar nombres simbólicos

Los valores numéricos pueden variar entre sistemas. Un nombre expresa la condición y mejora la portabilidad.

import errno

try:
    with open("config.ini", "rb") as archivo:
        datos = archivo.read()
except OSError as exc:
    if exc.errno == errno.ENOENT:
        print("Archivo no encontrado")
    else:
        raise

Cuando existe una excepción específica, suele ser más clara:

try:
    with open("config.ini", "rb") as archivo:
        datos = archivo.read()
except FileNotFoundError:
    print("Archivo no encontrado")

Usa errno cuando varios códigos comparten clase o una biblioteca nativa devuelve solo el entero.

Atributos de OSError

OSError suele ofrecer errno, strerror, filename y a veces filename2. No todas las instancias tienen datos completos.

try:
    origen.replace(destino)
except OSError as exc:
    print("código:", exc.errno)
    print("mensaje:", exc.strerror)
    print("archivo:", exc.filename)

No tomes decisiones con el texto de strerror. Cambia según idioma, plataforma y versión. Compara la clase o el código.

Convertir número en nombre

errno.errorcode mapea valores disponibles a sus nombres.

import errno

codigo = errno.EACCES
nombre = errno.errorcode.get(codigo, "ERROR_DESCONOCIDO")
print(codigo, nombre)

No todos los símbolos existen en todos los sistemas. Usa hasattr() o getattr() para código multiplataforma.

Convertir código en mensaje

os.strerror() devuelve la descripción del sistema.

import errno
import os

print(os.strerror(errno.ENOSPC))

El texto sirve para logs e interfaces, no como contrato estable. Devuelve un identificador interno separado del mensaje localizado.

Errores frecuentes de archivos

Valores comunes: ENOENT para ruta ausente; EACCES o EPERM para acceso denegado; EEXIST para destino existente; ENOTDIR cuando un componente no es directorio; EISDIR cuando se esperaba archivo; ENOSPC para disco lleno; EROFS para almacenamiento de solo lectura; y EXDEV en operaciones entre dispositivos.

Para archivos temporales y reemplazo atómico, consulta tempfile en Python. Incluso un flujo correcto debe manejar permisos y falta de espacio.

EXDEV entre filesystems

Path.rename() y os.rename() pueden fallar con EXDEV cuando origen y destino están en filesystems diferentes. La aplicación puede copiar, verificar y borrar el origen si esa semántica es aceptable.

import errno
import shutil

try:
    origen.replace(destino)
except OSError as exc:
    if exc.errno != errno.EXDEV:
        raise
    shutil.copy2(origen, destino)
    origen.unlink()

El fallback no conserva exactamente la atomicidad. Añade verificación de integridad y limpieza ante fallos parciales.

Operaciones no bloqueantes

EAGAIN, EWOULDBLOCK, EINPROGRESS y EALREADY aparecen con sockets y descriptores no bloqueantes. Python suele representarlos mediante BlockingIOError.

import errno

try:
    datos = sock.recv(4096)
except BlockingIOError as exc:
    if exc.errno in {errno.EAGAIN, errno.EWOULDBLOCK}:
        datos = None
    else:
        raise

En algunas plataformas EAGAIN y EWOULDBLOCK comparten valor. No hagas busy loop; espera disponibilidad con selectors o select.

Errores de red

Entre los códigos importantes están ECONNREFUSED, ECONNRESET, ECONNABORTED, ETIMEDOUT, EHOSTUNREACH, ENETUNREACH, EADDRINUSE y EADDRNOTAVAIL.

El guía de socketserver en Python aborda servidores y cierre. Para HTTP, urllib.error en Python separa respuestas HTTP de fallos de transporte.

Broken pipe

EPIPE ocurre al escribir en un pipe o socket cuyo lector cerró. Python normalmente genera BrokenPipeError.

try:
    conexion.sendall(payload)
except BrokenPipeError:
    cerrar_sesion()

Deja de enviar, elimina el descriptor del loop, libera recursos y registra un diagnóstico limitado.

Llamadas interrumpidas

EINTR indica una llamada interrumpida por señal. Desde PEP 475, varias APIs repiten automáticamente cuando el handler no lanza excepción. Bibliotecas nativas aún pueden exponer InterruptedError.

while True:
    try:
        return operacion()
    except InterruptedError:
        continue

Repite solo operaciones seguras. Una llamada puede haber producido efectos parciales.

Integración con ctypes

El artículo anterior, ctypes en Python, usa use_errno=True para mantener una copia thread-local leída mediante get_errno().

import errno
import os
from ctypes import CDLL, get_errno

lib = CDLL("libejemplo.so", use_errno=True)
resultado = lib.abrir_recurso()

if resultado == -1:
    codigo = get_errno()
    if codigo == errno.EACCES:
        raise PermissionError(codigo, os.strerror(codigo))
    raise OSError(codigo, os.strerror(codigo))

Lee el código inmediatamente. Otra llamada nativa puede sobrescribirlo.

Diferencias de plataforma

Linux, macOS, BSD, Windows y WASI ofrecen subconjuntos distintos. errno.errorcode refleja el entorno actual.

import errno

codigo_cuota = getattr(errno, "EDQUOT", None)
if codigo_cuota is not None:
    print("La cuota de disco puede identificarse")

Al enviar un error a otro servicio, no transmitas solo el entero. Incluye un código de aplicación y, opcionalmente, el símbolo y la plataforma.

Evitar capturas amplias

Convertir cualquier OSError en “archivo inexistente” oculta permisos, disco lleno y fallos de dispositivo.

try:
    cargar_configuracion()
except FileNotFoundError:
    crear_configuracion_predeterminada()

Captura solo condiciones que sabes resolver. Lo mismo vale para retries: un disco lleno no mejora con repetición inmediata.

Clasificar fallos reintentables

TRANSITORIOS = {
    errno.EAGAIN,
    errno.EINTR,
    errno.ETIMEDOUT,
}

def puede_reintentarse(exc: OSError) -> bool:
    return exc.errno in TRANSITORIOS

La decisión depende también de idempotencia. Repetir escrituras, pagos, borrados o POST puede duplicar efectos. Combina códigos, límites de intentos, jitter y backoff exponencial.

Logs estructurados

def error_para_log(exc: OSError) -> dict:
    return {
        "tipo": type(exc).__name__,
        "errno": exc.errno,
        "simbolo": errno.errorcode.get(exc.errno),
        "mensaje": exc.strerror,
    }

Añade la operación y un recurso redactado, no credenciales o rutas sensibles completas.

Pruebas recomendadas

Prueba archivos ausentes, acceso denegado, destinos existentes, directorio usado como archivo, almacenamiento de solo lectura, disco lleno, sockets rechazados, timeout, conexión resetada, I/O no bloqueante y símbolos ausentes.

Los tests unitarios pueden construir OSError con códigos conocidos, pero conserva tests de integración reales porque los mappings cambian entre sistemas.

Errores comunes

Los fallos frecuentes son comparar mensajes localizados, usar números mágicos, asumir que todos los símbolos existen, capturar cualquier OSError, repetir operaciones no idempotentes, leer errno nativo demasiado tarde y exponer códigos del sistema como API pública permanente.

Conclusión

errno aporta nombres significativos a los códigos de fallo del sistema. Complementa las excepciones específicas de Python y sigue siendo valioso en llamadas nativas e I/O no bloqueante.

Prefiere excepciones específicas, compara símbolos en vez de texto y diseña retries considerando el error y la operación. Consulta la documentación oficial de errno y la documentación oficial de OSError.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    African American man using a laptop in a well-organized library setting with colorful bookshelves.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ctypes en Python: usa bibliotecas C

    Aprende ctypes en Python para cargar bibliotecas C, definir tipos y punteros, gestionar memoria, callbacks, ABI y errores nativos.

    Ler mais

    Tempo de leitura: 6 minutos
    24/08/2026
    A person reads 'Python for Unix and Linux System Administration' indoors.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    expat en Python: parser XML de bajo nivel

    Aprende expat en Python para parsing XML de bajo nivel, handlers, namespaces, diagnósticos y protección contra amplificación y DoS.

    Ler mais

    Tempo de leitura: 5 minutos
    23/08/2026
    Detailed shot of a Jungle Carpet Python (Morelia spilota cheynei) in its natural habitat.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ElementInclude en Python: XInclude seguro

    Aprende ElementInclude en Python para usar XInclude con loaders seguros, base URL, profundidad máxima y bloqueo de rutas externas.

    Ler mais

    Tempo de leitura: 5 minutos
    23/08/2026
    A person reads 'Python for Unix and Linux System Administration' indoors.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    xmlreader en Python: controla parsers SAX

    Aprende xmlreader en Python para configurar parsers SAX, InputSource, parsing incremental, atributos, locators y seguridad XML.

    Ler mais

    Tempo de leitura: 5 minutos
    23/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    saxutils en Python: utilidades para XML

    Aprende saxutils en Python para escapar XML, preparar atributos, generar documentos, crear filtros SAX y evitar errores de contexto.

    Ler mais

    Tempo de leitura: 5 minutos
    23/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pulldom en Python: DOM parcial para XML

    Aprende pulldom en Python para procesar XML por eventos, expandir subárboles selectivos y reducir memoria con límites seguros.

    Ler mais

    Tempo de leitura: 5 minutos
    23/08/2026