posix en Python: llamadas Unix directas

Publicado el: 26/08/2026
Tempo de leitura: 7 minutos
A person reads 'Python for Unix and Linux System Administration' indoors.

El módulo posix expone llamadas de sistema comunes en plataformas compatibles con POSIX. Proporciona una interfaz de bajo nivel para archivos, directorios, procesos, descriptores, permisos, usuarios, grupos e información del sistema operativo. En la práctica, casi todo código de aplicación debería importar os, porque ofrece una capa más portable e incluye la mayor parte de la API útil de posix.

Conocer posix, sin embargo, ayuda a entender cómo Python se comunica con sistemas Unix como Linux, macOS y BSD. También resulta útil al investigar comportamientos específicos de la plataforma, crear herramientas administrativas, comparar builds del intérprete o comprender el origen de muchas funciones de os.

Disponibilidad y portabilidad

posix solo existe cuando Python fue compilado para un sistema que ofrece la interfaz correspondiente. Normalmente no está disponible en Windows. Por eso, una biblioteca multiplataforma no debería importarlo globalmente sin una alternativa.

try:
    import posix
except ImportError:
    posix = None

if posix is None:
    print("La interfaz POSIX no está disponible")

Incluso en Unix, las funciones individuales pueden variar según el kernel, la biblioteca C, las opciones de compilación y la versión de Python. Comprueba capacidades con hasattr() o, preferiblemente, con los conjuntos publicados por os.

Por qué conviene usar os

El módulo os selecciona la implementación adecuada para el sistema actual. En Unix, muchas de sus funciones se apoyan en posix; en Windows, otra implementación ofrece operaciones equivalentes. Así, os.open(), os.stat() y os.getpid() mantienen una interfaz pública consistente.

import os

print(os.getpid())
print(os.getcwd())

Importa posix directamente solo cuando el objetivo sea estudiar, probar o depender de comportamiento POSIX. Para programas normales, os es más claro y seguro.

Descriptores de archivo

Las llamadas de bajo nivel trabajan con descriptores enteros. open() abre una ruta y devuelve un descriptor; read() y write() transfieren bytes; close() libera el recurso.

import os

fd = os.open("datos.bin", os.O_RDONLY)
try:
    bloque = os.read(fd, 4096)
    print(len(bloque))
finally:
    os.close(fd)

El bloque finally es esencial cuando gestionas descriptores manualmente. Para archivos normales, la función global open() con with es más cómoda porque gestiona cierre, buffering, texto y encoding.

Flags de apertura

Las llamadas POSIX combinan flags como O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_APPEND y, cuando existe, O_CLOEXEC. El operador bit a bit | construye la configuración.

import os

flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
fd = os.open("nuevo.txt", flags, 0o600)
try:
    os.write(fd, b"contenido privado\n")
finally:
    os.close(fd)

O_EXCL junto con O_CREAT evita reemplazar un archivo existente y reduce condiciones de carrera. El modo 0o600 solicita acceso solo para el propietario, aunque la umask del proceso también afecta el permiso final.

Rutas como str o bytes

En Unix, una ruta puede expresarse como str o bytes. Usa texto en la mayoría de los programas. Los bytes son útiles cuando necesitas conservar nombres que no pueden decodificarse con el encoding del sistema de archivos.

No mezcles ambos tipos en una operación. Las funciones que reciben una ruta en bytes normalmente devuelven nombres en bytes. os.fsencode() y os.fsdecode() convierten de acuerdo con la política del sistema de archivos de Python.

Información de archivos con stat

stat() devuelve tamaño, timestamps, propietario, grupo, modo y otros campos. Usa el módulo stat para interpretar los bits del modo.

import os
import stat

info = os.stat("datos.bin", follow_symlinks=False)
print(info.st_size)
print(stat.filemode(info.st_mode))
print(stat.S_ISREG(info.st_mode))

Cuando la seguridad depende del objeto inspeccionado, evita la secuencia “comprobar una ruta y después abrirla”. Otro proceso podría sustituirla entre ambas operaciones. Prefiere APIs basadas en descriptores y parámetros como dir_fd y follow_symlinks cuando estén disponibles.

Enlaces simbólicos

stat() suele seguir enlaces simbólicos, mientras lstat() describe el propio enlace. La diferencia es importante en scanners, backups, instaladores y herramientas de limpieza.

import os

destino = os.readlink("acceso")
info_enlace = os.lstat("acceso")
print(destino, info_enlace.st_mode)

Nunca supongas que una ruta confiable sigue apuntando al mismo objeto. En directorios compartidos, un atacante puede cambiar un symlink y redirigir una operación privilegiada.

Permisos y umask

chmod() cambia bits de permiso. umask() define qué permisos solicitados se eliminan al crear objetos. Como la umask es estado global del proceso, modificarla en una aplicación con varias threads es arriesgado.

import os

os.chmod("nuevo.txt", 0o600)

No uses chmod(0o777) como arreglo universal. Concede únicamente lo necesario y considera ACL, políticas del container, volúmenes montados e identidad efectiva.

Usuario, grupo y proceso

Funciones como getpid(), getppid(), getuid(), geteuid(), getgid() y getegid() describen el proceso. La identidad real y efectiva pueden diferir en programas con privilegios especiales.

import os

print({
    "pid": os.getpid(),
    "uid": os.getuid(),
    "euid": os.geteuid(),
    "gid": os.getgid(),
})

Para convertir UID y GID en nombres, consulta pwd en Python y grp en Python. Esas bases de cuentas no son mecanismos de autenticación.

Variables de entorno

En POSIX, el entorno es una colección de claves y valores asociada al proceso. En Python, prefiere os.environ, un mapeo mutable cuyas modificaciones serán heredadas por futuros procesos hijos.

import os

modo = os.environ.get("APP_MODE", "development")
os.environ["APP_CHILD_FLAG"] = "1"

No registres todo el entorno. Puede contener tokens, contraseñas, endpoints privados y rutas sensibles. Valida los valores antes de usarlos en comandos o nombres de archivo.

Creación de procesos

POSIX ofrece primitivas como fork(), execve(), waitpid() y _exit(). Son poderosas, pero exigen controlar threads, buffers, locks y descriptores heredados.

Para ejecutar programas, prefiere subprocess. Su API gestiona argumentos, redirección, códigos de salida, timeouts y cierre de descriptores de forma más segura.

import subprocess

resultado = subprocess.run(
    ["uname", "-s"],
    check=True,
    capture_output=True,
    text=True,
    timeout=5,
)
print(resultado.stdout.strip())

Evita shell=True con datos no confiables. Pasa los argumentos como lista.

Fork y threads

Después de fork(), solo continúa en el hijo la thread que llamó a la función. Locks mantenidos por otras threads pueden quedar bloqueados para siempre. Clientes de bases de datos, logging, TLS y allocators también pueden conservar estados inconsistentes.

Las aplicaciones modernas deberían usar subprocess o un método de inicio adecuado de multiprocessing. Evita trabajo Python complejo entre fork() y exec() en procesos multithread.

Descriptores heredados

Un descriptor abierto puede filtrarse a un proceso hijo y mantener archivos, sockets o pipes activos. Python crea muchos descriptores como no heredables por defecto, pero extensiones nativas y configuraciones explícitas pueden cambiarlo.

Usa os.get_inheritable(), os.set_inheritable() y opciones de subprocess conscientemente. fcntl en Python explica flags y locks de descriptores Unix.

Operaciones relativas a directorios

Muchas funciones aceptan dir_fd. En lugar de concatenar rutas, abre un directorio confiable y resuelve nombres respecto de su descriptor. Esto puede reducir carreras y facilitar operaciones restringidas.

import os

base_fd = os.open("datos", os.O_RDONLY | os.O_DIRECTORY)
try:
    fd = os.open("item.txt", os.O_RDONLY, dir_fd=base_fd)
    try:
        print(os.read(fd, 100))
    finally:
        os.close(fd)
finally:
    os.close(base_fd)

No toda función o plataforma soporta dir_fd. Consulta os.supports_dir_fd.

Sincronización y durabilidad

fsync() solicita que el sistema escriba datos y metadatos asociados al descriptor. Para reemplazos críticos, escribe un archivo temporal en el mismo sistema de archivos, sincronízalo, renómbralo atómicamente y, cuando corresponda, sincroniza el directorio.

Una llamada exitosa no protege contra toda falla de hardware o caché. La durabilidad depende del sistema de archivos, dispositivo, opciones de montaje e infraestructura.

Errores y OSError

Las fallas de llamadas del sistema aparecen como subclases de OSError, entre ellas FileNotFoundError, PermissionError, FileExistsError e IsADirectoryError.

from pathlib import Path

try:
    datos = Path("config.ini").read_text(encoding="utf-8")
except FileNotFoundError:
    datos = ""
except PermissionError as error:
    raise RuntimeError("sin permiso para leer config.ini") from error

Captura la excepción más específica que permita responder de manera útil. No ocultes fallas inesperadas con except OSError: pass.

Límites de recursos

Las llamadas POSIX pueden fallar por agotamiento de descriptores, memoria, espacio en disco o límites de procesos. resource en Python explica cómo consultar y definir varios límites Unix.

Gestiona errores, configura timeouts y limita el volumen de entrada. Un recorrido de directorios o un proceso batch debería cerrar recursos progresivamente.

Pruebas en sistemas reales

Los containers no reproducen todas las diferencias entre macOS, Linux y BSD. Prueba permisos, symlinks, rutas en bytes, mounts de solo lectura, sistemas de archivos de red, disco lleno, UIDs distintos, umask, señales y herencia de descriptores.

Ejecuta pruebas con privilegios reducidos. Probar solo como administrador puede ocultar errores de permisos y suposiciones inseguras.

Errores comunes

Los problemas frecuentes incluyen importar posix cuando os sería suficiente, suponer que todas las funciones existen, olvidar cerrar descriptores, mezclar rutas de texto y bytes, seguir symlinks sin intención, cambiar la umask global desde varias threads, usar fork() sin seguridad y capturar OSError sin diagnóstico.

Conclusión

posix muestra la capa de llamadas de sistema Unix utilizada por Python, pero os debería seguir siendo la interfaz predeterminada para la mayoría de los proyectos. Usa APIs de alto nivel cuando expresen mejor la intención y recurre a descriptores, flags y operaciones relativas a directorios cuando realmente necesites control preciso.

Valida capacidades, cierra recursos, reduce privilegios y trata las rutas compartidas como mutables. Consulta la documentación oficial de posix y la documentación de os.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    A male software engineer working on code in a modern office setting.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    curses en Python: interfaces de terminal

    Aprende curses en Python para crear interfaces de terminal con ventanas, colores, teclado, resize, Unicode y cleanup seguro.

    Ler mais

    Tempo de leitura: 6 minutos
    26/08/2026
    Creative concept with coffee cup and paper question marks on a table.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    grp en Python: consulta grupos Unix

    Aprende grp en Python para consultar grupos Unix, GIDs, miembros, ownership, grupos suplementarios, NSS y containers.

    Ler mais

    Tempo de leitura: 5 minutos
    26/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pwd en Python: consulta usuarios Unix

    Aprende pwd en Python para consultar usuarios Unix por UID o login, obtener home, shell y ownership sin usar la

    Ler mais

    Tempo de leitura: 6 minutos
    26/08/2026
    Close-up of stacked logs showing natural textures and patterns, suitable for firewood or decor.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    syslog en Python: envía logs a Unix

    Aprende syslog en Python para enviar logs Unix con prioridades, facilities, máscaras, contenido estructurado y protección contra log injection.

    Ler mais

    Tempo de leitura: 4 minutos
    26/08/2026
    A CPU and RAM sticks displayed on a white surface, showcasing computer hardware components.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    resource en Python: límites de CPU y memoria

    Aprende resource en Python para medir CPU, pico de memoria y page faults, y limitar archivos, procesos, descriptors y address

    Ler mais

    Tempo de leitura: 5 minutos
    26/08/2026
    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