resource en Python: límites de CPU y memoria

Publicado el: 26/08/2026
Tempo de leitura: 5 minutos
A CPU and RAM sticks displayed on a white surface, showcasing computer hardware components.

El módulo resource mide y limita recursos usados por procesos Unix. Puede informar tiempo de CPU, page faults, context switches y pico de memoria, además de imponer cotas para file descriptors, tamaño de archivos, address space, creación de procesos y otros recursos soportados.

Estos controles son útiles al ejecutar plugins, compiladores, conversores, tareas de usuarios o subprocesses que no deben consumir CPU, memoria o disco sin límite. No sustituyen containers, cgroups, sandboxes o usuarios sin privilegios, pero añaden una capa defensiva.

Disponibilidad

resource existe en Unix y no en WASI. Las constantes cambian por plataforma, así que comprueba con hasattr().

import resource

if hasattr(resource, "RLIMIT_AS"):
    print(resource.getrlimit(resource.RLIMIT_AS))

No asumas que Linux, macOS y BSD ofrecen o aplican los mismos límites.

Soft y hard limit

Cada recurso tiene un par (soft, hard). El soft se aplica actualmente. Un proceso puede bajarlo y normalmente volver a subirlo hasta el hard. Elevar el hard requiere privilegios.

soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print("Soft:", soft, "Hard:", hard)

RLIM_INFINITY representa ilimitado cuando el sistema lo permite.

No reduzcas el hard sin necesidad

Después de bajar el hard, un proceso sin privilegios no puede restaurarlo. Para limitaciones temporales, conserva hard y cambia solo soft.

soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
resource.setrlimit(resource.RLIMIT_NOFILE, (min(256, hard), hard))

Incluso cambiar el soft del proceso principal puede romper bibliotecas cargadas después. Prefiere un hijo dedicado.

Limitar file descriptors

RLIMIT_NOFILE controla cuántos descriptors pueden estar abiertos.

def limitar_fds(maximo=128):
    soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
    valor = min(maximo, hard)
    resource.setrlimit(resource.RLIMIT_NOFILE, (valor, hard))

Al agotarse, operaciones pueden lanzar EMFILE. Cierra archivos, sockets y pipes correctamente.

Limitar CPU

RLIMIT_CPU cuenta segundos de CPU, no tiempo de reloj.

resource.setrlimit(resource.RLIMIT_CPU, (2, 3))

Superar soft envía SIGXCPU. Llegar a hard puede terminar el proceso.

Una tarea dormida o esperando red puede durar mucho más sin consumir CPU. Usa también timeout externo.

Manejar SIGXCPU

import signal


def cpu_excedida(signum, frame):
    guardar_estado_minimo()
    raise SystemExit(124)

if hasattr(signal, "SIGXCPU"):
    signal.signal(signal.SIGXCPU, cpu_excedida)

Mantén el handler corto. signal en Python explica los riesgos de locks y logging.

Limitar tamaño de archivos

RLIMIT_FSIZE limita el tamaño máximo de un archivo creado.

limite = 10 * 1024 * 1024
resource.setrlimit(resource.RLIMIT_FSIZE, (limite, limite))

No limita el número de archivos ni todo el filesystem. Usa cuota o directorio aislado para protección adicional.

Limitar address space

RLIMIT_AS limita memoria virtual.

if hasattr(resource, "RLIMIT_AS"):
    limite = 512 * 1024 * 1024
    resource.setrlimit(resource.RLIMIT_AS, (limite, limite))

Bibliotecas científicas, mmap, shared objects y allocators reservan espacio virtual que no equivale al RSS. Un valor bajo puede impedir imports o generar MemoryError.

RLIMIT_DATA y RLIMIT_RSS

RLIMIT_DATA tradicionalmente limita heap, pero allocations modernas pueden evitarlo. RLIMIT_RSS puede ser advisory.

Para memoria en producción, cgroups o limits de container suelen ser más predecibles.

Stack

RLIMIT_STACK limita la stack del thread principal. Bajarlo demasiado puede provocar crash en recursión, extensiones C o inicialización.

Número de procesos

RLIMIT_NPROC limita creación de procesos según la plataforma.

if hasattr(resource, "RLIMIT_NPROC"):
    soft, hard = resource.getrlimit(resource.RLIMIT_NPROC)
    resource.setrlimit(resource.RLIMIT_NPROC, (min(32, hard), hard))

Threads pueden contar y servicios con el mismo usuario pueden competir.

Aplicar límites en un wrapper

preexec_fn puede ser peligroso en un padre multithread. Un wrapper simple es más seguro.

# wrapper_limitado.py
import os
import resource
import sys

resource.setrlimit(resource.RLIMIT_CPU, (2, 3))
resource.setrlimit(resource.RLIMIT_FSIZE, (10_000_000, 10_000_000))
os.execvp(sys.argv[1], sys.argv[1:])

El padre inicia el wrapper con lista de argumentos, sin shell.

prlimit()

En Linux, prlimit() consulta o modifica límites de otro proceso con permisos.

if hasattr(resource, "prlimit"):
    anterior = resource.prlimit(pid, resource.RLIMIT_NOFILE, (128, 128))
    print(anterior)

Puede lanzar ProcessLookupError o PermissionError. Verifica identidad porque los PIDs se reutilizan.

Auditoría

setrlimit() y prlimit() generan eventos de auditoría.

getrusage()

getrusage() informa sobre el proceso actual, hijos recolectados o thread actual.

uso = resource.getrusage(resource.RUSAGE_SELF)
print("CPU usuario:", uso.ru_utime)
print("CPU sistema:", uso.ru_stime)
print("Pico RSS:", uso.ru_maxrss)

RUSAGE_SELF incluye todas las threads. RUSAGE_CHILDREN incluye hijos terminados y esperados.

Unidades de ru_maxrss

La unidad depende de la plataforma. Linux normalmente devuelve KiB y macOS bytes. Normaliza antes de mostrar MB.

import platform

valor = uso.ru_maxrss
rss_bytes = valor if platform.system() == "Darwin" else valor * 1024

Valida esta regla en otros Unix.

Pico no es memoria actual

ru_maxrss representa el máximo observado y no disminuye al liberar memoria.

Para una serie temporal, usa procfs, psutil o métricas del container.

Tiempo de CPU

ru_utime mide user mode y ru_stime kernel mode.

antes = resource.getrusage(resource.RUSAGE_SELF)
ejecutar_trabajo()
despues = resource.getrusage(resource.RUSAGE_SELF)

cpu = (despues.ru_utime - antes.ru_utime) + (despues.ru_stime - antes.ru_stime)

Para microbenchmarks, usa timeit.

Page faults

ru_minflt cuenta faults sin I/O y ru_majflt los que requieren almacenamiento. Dependen de cache, kernel y entorno.

Context switches

ru_nvcsw cuenta cambios voluntarios y ru_nivcsw involuntarios. Muchos involuntarios pueden indicar competencia por CPU.

Operaciones de bloque

ru_inblock y ru_oublock representan operaciones, no bytes.

Hijos recolectados

Para aparecer en RUSAGE_CHILDREN, el hijo debe terminar y ser recolectado con wait() o waitpid().

Tamaño de página

print(resource.getpagesize())

No describe necesariamente huge pages ni todos los detalles de hardware.

Los límites no son sandbox

Un proceso limitado puede acceder a archivos permitidos, red, entorno y credenciales. Combina rlimits con usuario sin privilegios, directorios aislados, allowlist y containers.

Aplicar temprano

Define límites antes de cargar contenido no confiable. Reducir una cota no deshace recursos ya consumidos.

Diagnóstico

Registra los límites efectivos. Al terminar por señal, informa que CPU, archivos o memoria pueden ser responsables sin afirmar certeza absoluta.

Pruebas

Prueba constantes ausentes, soft mayor que hard, intento de subir hard, CPU-bound, sleep, archivos, descriptors, imports bajo RLIMIT_AS, hijos, threads, Linux/macOS y container.

Errores comunes

Los fallos frecuentes son limitar el proceso principal, confundir CPU y wall time, tratar ru_maxrss como memoria actual, ignorar unidades, bajar hard de forma irreversible, asumir RLIMIT_RSS rígido y llamar sandbox a los rlimits.

Conclusión

resource mide consumo e impone cotas Unix básicas. Funciona mejor en procesos hijos dedicados con limits definidos antes del trabajo y monitoreo externo.

Comprueba constantes, normaliza métricas y combina rlimits con aislamiento real. Consulta la documentación oficial de resource y getrlimit(2).

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Close-up of a person using a metro card machine for public transport payment indoors.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pty en Python: automatiza terminales Unix

    Aprende pty en Python para ejecutar y probar programas interactivos, controlar pseudo-terminales, EOF, resize, señales y timeouts.

    Ler mais

    Tempo de leitura: 5 minutos
    25/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tty en Python: modos raw y cbreak

    Aprende tty en Python para modos raw y cbreak, lectura de teclas, secuencias, Unicode y restauración segura del terminal Unix.

    Ler mais

    Tempo de leitura: 5 minutos
    25/08/2026
    Laptop displaying code with reflection, perfect for tech and programming themes.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    termios en Python: control seguro del terminal

    Aprende termios en Python para modo canónico, echo, lectura de teclas, baud rate, colas, ventana y restauración segura del TTY.

    Ler mais

    Tempo de leitura: 5 minutos
    25/08/2026
    Multiple padlocks securing a green chain link fence, symbolizing safety and protection.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fcntl en Python: locks y control de archivos

    Aprende fcntl en Python para locks, flags de descriptors, ioctl, pipes y control Unix, evitando buffers inválidos y corrupción de

    Ler mais

    Tempo de leitura: 5 minutos
    25/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    readline en Python: historial y autocomplete

    Aprende readline en Python para historial, autocompletado, edición de línea, GNU Readline, libedit y prompts seguros en terminal.

    Ler mais

    Tempo de leitura: 5 minutos
    25/08/2026
    Vibrant green tree python elegantly coiled on branch, showcasing its natural beauty.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    io en Python: domina streams y buffers

    Aprende io en Python para streams de texto y bytes, buffering, encoding, StringIO, BytesIO, I/O bruto e interfaces file-like.

    Ler mais

    Tempo de leitura: 6 minutos
    24/08/2026