termios en Python: control seguro del terminal

Publicado el: 25/08/2026
Tempo de leitura: 5 minutos
Laptop displaying code with reflection, perfect for tech and programming themes.

El módulo termios expone el control POSIX de terminales TTY en Unix. Permite activar o desactivar echo, cambiar entre entrada canónica y lectura carácter por carácter, configurar velocidades seriales, gestionar colas y consultar el tamaño de la ventana.

Estas operaciones modifican estado compartido del terminal asociado al file descriptor. Si el programa termina sin restaurarlo, el shell puede quedar sin echo, con teclas de control desactivadas o en un modo aparentemente roto. Guarda siempre los atributos originales y restáuralos en finally.

Disponibilidad

termios solo existe en Unix con soporte POSIX TTY. Windows usa APIs distintas y el descriptor debe estar conectado a un terminal real.

import os
import sys

if not os.isatty(sys.stdin.fileno()):
    raise RuntimeError("stdin no está conectado a un TTY")

La entrada redirigida desde un pipe o archivo no tiene los mismos atributos.

Estructura de tcgetattr()

tcgetattr(fd) devuelve siete elementos:

[iflag, oflag, cflag, lflag, ispeed, ospeed, cc]

Representan flags de entrada, salida, control y comportamiento local, velocidades y caracteres especiales. Interpreta todo mediante constantes simbólicas de termios.

Guardar y restaurar

import sys
import termios

fd = sys.stdin.fileno()
original = termios.tcgetattr(fd)
nuevo = termios.tcgetattr(fd)

try:
    nuevo[3] &= ~termios.ECHO
    termios.tcsetattr(fd, termios.TCSADRAIN, nuevo)
    secreto = input("Contraseña: ")
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, original)
    print()

Haz dos llamadas o una copia profunda porque la lista cc es mutable. Una copia superficial puede compartirla.

Cuándo aplicar cambios

TCSANOW aplica de inmediato. TCSADRAIN espera la salida pendiente. TCSAFLUSH también descarta entrada no leída.

Para desactivar echo en un prompt, TCSADRAIN evita cortar texto ya enviado.

Echo

El bit ECHO controla si los caracteres aparecen en pantalla.

atributos[3] &= ~termios.ECHO

Desactivar echo no vuelve la captura automáticamente segura. Para contraseñas comunes, prefiere getpass.getpass().

Modo canónico

Con ICANON activo, la entrada llega después de Enter y el driver realiza edición básica. Al desactivarlo, las lecturas pueden devolver datos antes de una línea completa.

atributos[3] &= ~termios.ICANON

El modo no canónico sirve para juegos, hotkeys e interfaces en pantalla completa, pero obliga a procesar bytes y secuencias de escape.

VMIN y VTIME

En cc, VMIN y VTIME controlan las lecturas no canónicas.

atributos[6][termios.VMIN] = 1
atributos[6][termios.VTIME] = 0

VMIN 1 y VTIME 0 espera al menos un byte. VMIN 0 con VTIME positivo crea un timeout en décimas de segundo.

Leer una tecla

import os
import sys
import termios

fd = sys.stdin.fileno()
original = termios.tcgetattr(fd)
nuevo = termios.tcgetattr(fd)
nuevo[3] &= ~(termios.ICANON | termios.ECHO)
nuevo[6][termios.VMIN] = 1
nuevo[6][termios.VTIME] = 0

try:
    termios.tcsetattr(fd, termios.TCSADRAIN, nuevo)
    tecla = os.read(fd, 1)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, original)

print(tecla)

Una tecla visible puede generar varios bytes. Las flechas y teclas de función producen secuencias de escape.

Unicode

os.read() devuelve bytes. Un carácter UTF-8 puede ocupar varios, por lo que un byte no equivale necesariamente a un carácter.

Usa un decoder incremental o analiza el protocolo del terminal.

Señales y teclas de control

ISIG permite que Ctrl+C y Ctrl+Z generen señales. Desactivarlo convierte esos bytes en entrada normal.

Ofrece otra tecla de salida y restaura el estado tras excepciones. Consulta signal en Python.

Mapeo de entrada

ICRNL, INLCR e IGNCR controlan conversiones entre carriage return y newline. Modificarlos afecta Enter y protocolos seriales.

Cambia solo los bits necesarios.

Procesamiento de salida

OPOST habilita transformaciones de salida. Un modo raw puede desactivarlo, alterando también el comportamiento de newline y cursor.

Para casos comunes, usa funciones de tty o una biblioteca de terminal completa.

Flags de hardware

cflag incluye tamaño de carácter, paridad, stop bits y control de flujo. Son importantes en puertos seriales.

Una configuración incorrecta puede producir datos ilegibles o bloquear la comunicación.

Baud rate

ispeed y ospeed usan constantes como B9600 y B115200.

atributos[4] = termios.B115200
atributos[5] = termios.B115200

No todas las velocidades están disponibles. Para producción, pyserial suele ser más portable.

tcdrain()

tcdrain(fd) espera que toda la salida en cola se transmita. Es útil antes de cambiar parámetros o cerrar un dispositivo serial.

Puede bloquear si el hardware está lento o desconectado.

tcflush()

termios.tcflush(fd, termios.TCIFLUSH)

TCIFLUSH descarta entrada, TCOFLUSH salida y TCIOFLUSH ambas. Descartar salida puede perder comandos ya aceptados.

Control de flujo

tcflow() suspende o reanuda entrada o salida con acciones como TCOOFF y TCOON. No lo confundas con control de flujo de hardware.

Enviar break

tcsendbreak(fd, duration) envía una condición break en líneas seriales. Duración cero significa aproximadamente 0,25 a 0,5 segundos; otros valores dependen del sistema.

Tamaño de ventana

Desde Python 3.11, tcgetwinsize() devuelve filas y columnas.

filas, columnas = termios.tcgetwinsize(sys.stdout.fileno())
print(filas, columnas)

tcsetwinsize() establece el tamaño cuando la plataforma lo soporta, algo útil con pseudo-terminales.

SIGWINCH

Después de un resize, procesos Unix suelen recibir SIGWINCH. Haz que el handler marque una flag y recalcula el layout en el loop principal.

El conjunto final sobre curses cubre interfaces de pantalla completa.

Context manager reutilizable

from contextlib import contextmanager
import termios

@contextmanager
def atributos_temporales(fd, modificar):
    original = termios.tcgetattr(fd)
    nuevo = termios.tcgetattr(fd)
    modificar(nuevo)
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, nuevo)
        yield
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, original)

Centralizar la restauración reduce rutas de error olvidadas.

Fork y subprocesses

Los hijos pueden heredar el mismo terminal y observar atributos temporales. Evita iniciar procesos ajenos mientras el TTY está modificado.

Usa un pseudo-terminal cuando necesites aislar una aplicación interactiva.

Threads

El estado pertenece al terminal, no al thread. Dos threads cambiando flags pueden restaurar valores fuera de orden. Centraliza el control en uno solo.

Recuperación manual

Si una aplicación deja el terminal sin echo, stty sane suele restaurar un estado razonable. Documenta el comando en herramientas experimentales.

Pruebas

Prueba terminal real y entrada redirigida, Ctrl+C, excepción durante lectura, Unicode, flechas, resize, subprocesses, serial, VMIN/VTIME y restauración tras fallo.

Usa pty para tests automatizados, pero también prueba manualmente.

Errores comunes

Los fallos frecuentes son omitir finally, modificar la lista original, hacer copia superficial de cc, asumir una tecla por byte, desactivar ISIG sin salida alternativa, operar sobre stdin redirigido y cambiar demasiadas flags.

Conclusión

termios proporciona control preciso de terminales POSIX y puertos seriales. Úsalo cuando necesites flags de bajo nivel; para tareas comunes, prefiere tty, getpass, curses o bibliotecas especializadas.

Guarda y restaura el estado, cambia solo los bits necesarios y prueba en el Unix objetivo. Consulta la documentación oficial de termios y termios(3).

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    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
    Vibrant green tree python elegantly coiled on branch, showcasing its natural beauty.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    select en Python: monitorea varios I/O

    Aprende select en Python para monitorear sockets y pipes, tratar I/O parcial, backpressure, poll, epoll, señales y diferencias de plataforma.

    Ler mais

    Tempo de leitura: 6 minutos
    24/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

    signal en Python: cierre correcto

    Aprende signal en Python para manejar SIGTERM y SIGINT, detener servicios, usar timers, wakeup FD y evitar deadlocks en handlers.

    Ler mais

    Tempo de leitura: 7 minutos
    24/08/2026
    Creative concept showing the word 'error' with cut out letters on a table with scissors and paper.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    errno en Python: errores del sistema

    Aprende errno en Python para interpretar códigos del sistema, tratar OSError, archivos, red, retries y llamadas nativas de forma portable.

    Ler mais

    Tempo de leitura: 4 minutos
    24/08/2026