termios no Python: controle seguro do terminal

Publicado em: 25/08/2026
Tempo de leitura: 6 minutos
Multiple padlocks securing a green chain link fence, symbolizing safety and protection.

O módulo termios expõe o controle POSIX de terminais TTY em sistemas Unix. Com ele, uma aplicação pode ativar ou desativar echo, alternar entre modo canônico e leitura caractere a caractere, configurar velocidades, controlar filas de entrada e saída e consultar o tamanho da janela.

Essas operações alteram o estado global do terminal associado ao file descriptor. Se o programa encerrar sem restaurar os atributos, o shell pode ficar sem echo, com teclas especiais desativadas ou em modo aparentemente travado. A regra principal é salvar o estado original e restaurá-lo em finally.

Disponibilidade

termios existe apenas em sistemas Unix que oferecem controle POSIX de TTY. Windows usa APIs diferentes. Também é necessário que o file descriptor esteja ligado a um terminal real.

import os
import sys

if not os.isatty(sys.stdin.fileno()):
    raise RuntimeError("stdin não está conectado a um TTY")

Entrada redirecionada por pipe ou arquivo não possui os mesmos atributos. Detecte isso antes de modificar o terminal.

Estrutura retornada por tcgetattr()

tcgetattr(fd) retorna sete elementos:

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

iflag controla entrada, oflag saída, cflag parâmetros de hardware, lflag comportamento local, ispeed e ospeed velocidades e cc caracteres de controle.

Use sempre constantes simbólicas do módulo. Não codifique números encontrados em outra plataforma.

Salvar e restaurar

import sys
import termios

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

try:
    novo[3] &= ~termios.ECHO
    termios.tcsetattr(fd, termios.TCSADRAIN, novo)
    segredo = input("Senha: ")
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, original)
    print()

Faça duas chamadas ou copie profundamente a lista, porque cc também é mutável. Uma cópia superficial pode compartilhar o subarray.

TCSANOW, TCSADRAIN e TCSAFLUSH

TCSANOW aplica imediatamente. TCSADRAIN espera a saída pendente ser transmitida. TCSAFLUSH também descarta entrada ainda não lida.

Para desligar echo em um prompt, TCSADRAIN evita cortar texto já enviado. Use TCSAFLUSH apenas quando descartar teclas pendentes for intencional.

Echo

O bit ECHO determina se caracteres digitados aparecem na tela.

atributos[3] &= ~termios.ECHO

Desligar echo não torna a captura de senha automaticamente segura. Processos privilegiados, keyloggers e o próprio código ainda podem acessar o valor. Para senhas comuns, prefira getpass.getpass().

Modo canônico

Com ICANON ativo, a linha é entregue após Enter e o driver processa edição básica. Ao removê-lo, leituras podem retornar antes do fim da linha.

atributos[3] &= ~termios.ICANON

Modo não canônico é útil para jogos, atalhos e interfaces em tela cheia, mas exige tratar cada byte, sinais e sequências de escape.

VMIN e VTIME

No array cc, VMIN e VTIME controlam leituras não canônicas.

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

Com VMIN 1 e VTIME 0, a leitura aguarda ao menos um byte. Com VMIN 0 e VTIME positivo, existe timeout em décimos de segundo. As combinações possuem semântica específica POSIX; teste no sistema alvo.

Leitura de uma tecla

import os
import sys
import termios

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

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

print(tecla)

Uma tecla visual pode gerar vários bytes. Setas e teclas de função normalmente produzem sequências de escape.

Unicode

os.read() retorna bytes. Um caractere UTF-8 pode ocupar vários bytes, portanto ler apenas um byte não produz necessariamente um caractere completo.

Use decoder incremental de codecs ou leia sequências conforme o protocolo do terminal. Não faça byte.decode() isolado presumindo ASCII.

Teclas especiais e sinais

O flag ISIG permite que caracteres como Ctrl+C e Ctrl+Z gerem sinais. Removê-lo transforma esses bytes em entrada normal.

Desativar ISIG pode impedir o usuário de interromper a aplicação. Ofereça uma tecla de saída e restaure o terminal mesmo diante de exceções. Veja signal no Python.

Mapeamento de entrada

Flags como ICRNL, INLCR e IGNCR controlam conversão entre carriage return e newline. Alterá-las afeta Enter e protocolos seriais.

Modifique apenas os bits necessários, preservando o restante.

Processamento de saída

OPOST habilita processamento de saída. Em modo raw, ele pode ser desativado para evitar conversões. Isso também pode fazer newline não retornar o cursor à coluna inicial.

Aplicações interativas geralmente devem usar as funções de conveniência do módulo tty ou uma biblioteca como curses em vez de reconstruir todos os flags.

Parâmetros de hardware

cflag inclui tamanho de caractere, paridade, stop bits e controle do receptor. Essas opções são relevantes para portas seriais.

Constantes e suporte variam por driver. Configuração errada pode produzir dados ilegíveis, bloquear comunicação ou ignorar controle de fluxo.

Baud rate

ispeed e ospeed representam velocidades de entrada e saída usando constantes como B9600 e B115200.

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

Nem toda velocidade está disponível. Para comunicação serial de produção, uma biblioteca como pyserial oferece API mais portátil.

tcdrain()

tcdrain(fd) espera toda saída enfileirada ser transmitida. É útil antes de trocar parâmetros de linha ou fechar uma porta serial.

A chamada pode bloquear por tempo significativo se o dispositivo estiver lento ou desconectado. Use arquitetura que permita cancelamento.

tcflush()

tcflush() descarta filas.

termios.tcflush(fd, termios.TCIFLUSH)

TCIFLUSH descarta entrada, TCOFLUSH saída e TCIOFLUSH ambas. Descartar saída pode perder comandos já aceitos pela aplicação.

tcflow()

tcflow() suspende ou retoma entrada e saída por software com ações como TCOOFF e TCOON.

Não confunda com controle de fluxo de hardware. A disponibilidade e interação com drivers precisam de testes.

Enviar break

tcsendbreak(fd, duration) envia uma condição break em linhas seriais. Com duração zero, POSIX define aproximadamente 0,25 a 0,5 segundo; valores diferentes possuem significado dependente do sistema.

Tamanho da janela

Desde Python 3.11, tcgetwinsize() retorna linhas e colunas.

linhas, colunas = termios.tcgetwinsize(sys.stdout.fileno())
print(linhas, colunas)

tcsetwinsize() altera o tamanho associado ao TTY quando suportado. Em pseudo-terminais, isso ajuda a simular resize.

SIGWINCH

Quando a janela muda, processos Unix normalmente recebem SIGWINCH. Recalcule layout fora do handler ou marque uma flag para o loop principal.

O módulo curses, abordado no último conjunto deste lote, gerencia boa parte do redimensionamento de interfaces em tela cheia.

Context manager para estado

from contextlib import contextmanager
import termios

@contextmanager
def atributos_temporarios(fd, alterar):
    original = termios.tcgetattr(fd)
    novo = termios.tcgetattr(fd)
    alterar(novo)
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, novo)
        yield
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, original)

Centralizar a restauração reduz o risco de esquecer um caminho de erro.

Fork e subprocessos

Processos filhos podem herdar o mesmo terminal e observar atributos alterados. Evite iniciar subprocessos enquanto o terminal está em estado temporário, a menos que isso faça parte do protocolo.

Um filho que muda o TTY pode afetar o pai. Use pseudo-terminal quando precisar isolar uma aplicação interativa.

Threads

O estado pertence ao terminal, não a uma thread. Duas threads alterando flags podem restaurar valores fora de ordem. Concentre o controle de terminal em uma única thread e use locks de aplicação apenas fora de signal handlers.

Recuperação manual

Se um programa falhar e deixar o terminal sem echo, o comando Unix stty sane costuma restaurar configurações razoáveis. Documente isso para ferramentas experimentais.

Testes

Teste terminal real e entrada redirecionada, Ctrl+C, exceção durante leitura, Unicode, setas, resize, suspensão, subprocessos, porta serial, VMIN/VTIME e restauração após crash.

Use pty para testes automatizados de TTY, mas ainda faça testes manuais em terminais suportados.

Erros comuns

Os erros mais frequentes são não usar finally, modificar a lista original, fazer cópia superficial de cc, presumir que uma tecla equivale a um byte, desligar ISIG sem saída alternativa, usar stdin redirecionado, alterar flags demais e não testar liberação após exceção.

Conclusão

termios oferece controle preciso de terminais POSIX e portas seriais. Use-o quando realmente precisar de flags de baixo nível; para operações comuns, prefira tty, getpass, curses ou bibliotecas especializadas.

Salve e restaure o estado, altere somente os bits necessários e teste no Unix alvo. Consulte a documentação oficial de termios e o manual termios(3).

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Detailed close-up of a combination lock with numbers in focus, highlighting security and privacy.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    fcntl no Python: locks e controle de arquivos

    Aprenda fcntl no Python para locks, flags de descritores, ioctl, pipes e controle Unix, evitando buffers incorretos e corrupção de

    Ler mais

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

    readline no Python: histórico e autocomplete

    Aprenda readline no Python para histórico, autocomplete, edição de linha, GNU Readline, libedit e prompts seguros no terminal.

    Ler mais

    Tempo de leitura: 6 minutos
    25/08/2026
    Serene stream flowing through Bavarian mountains, capturing winter beauty and natural tranquility.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    io no Python: domine streams e buffers

    Aprenda io no Python para trabalhar com streams de texto e bytes, buffering, encoding, StringIO, BytesIO e I/O bruto com

    Ler mais

    Tempo de leitura: 7 minutos
    24/08/2026
    Business professional analyzing financial data on multiple computer monitors at his workspace.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    select no Python: monitore vários I/Os

    Aprenda select no Python para monitorar sockets e pipes, tratar leituras parciais, backpressure, epoll, poll e sinais sem busy loop.

    Ler mais

    Tempo de leitura: 7 minutos
    24/08/2026
    View of multiple railway tracks with signals and buildings in an urban setting during daytime.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    signal no Python: encerre processos bem

    Aprenda signal no Python para tratar SIGTERM e SIGINT, encerrar serviços, usar timers, wakeup FD e coordenar shutdown sem deadlocks.

    Ler mais

    Tempo de leitura: 7 minutos
    24/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    errno no Python: entenda erros do sistema

    Aprenda errno no Python para interpretar códigos do sistema, tratar OSError, rede, arquivos, retries e chamadas nativas de forma portátil.

    Ler mais

    Tempo de leitura: 6 minutos
    24/08/2026