rlcompleter no Python: autocompletar REPL

Publicado em: 13/08/2026
Tempo de leitura: 6 minutos
Editor de código representando autocompletar em REPL com rlcompleter no Python

O módulo rlcompleter no Python fornece a função de autocompletar usada pelo modo interativo quando o readline está disponível. Ele sugere identificadores, palavras-chave, nomes definidos no namespace e atributos depois de um ponto. Esse comportamento pode ser incorporado em REPLs customizados, consoles administrativos, editores internos e ferramentas de ensino.

Apesar de pequeno, o módulo merece atenção de segurança. Para completar uma expressão pontuada, ele tenta resolver o objeto até o último ponto. Funções comuns não são chamadas, mas propriedades dinâmicas e __getattr__() podem ser acionados. Portanto, completar atributos não é necessariamente uma operação sem efeitos colaterais.

Como o rlcompleter funciona

A classe principal é rlcompleter.Completer. Seu método complete(text, state) é chamado repetidamente com estados 0, 1, 2 e assim por diante, até retornar None.

from rlcompleter import Completer

completer = Completer({'cliente': object(), 'calcular': lambda: None})
estado = 0
while True:
    sugestao = completer.complete('cal', estado)
    if sugestao is None:
        break
    print(sugestao)
    estado += 1

Esse protocolo foi desenhado para readline.set_completer(), mas também pode alimentar interfaces próprias.

Integração com readline

Em sistemas Unix com readline, importar rlcompleter normalmente registra automaticamente um completer no modo interativo. Em uma aplicação customizada, a configuração pode ser explícita.

import readline
from rlcompleter import Completer

namespace = {'status': mostrar_status, 'versao': '2.1'}
readline.set_completer(Completer(namespace).complete)
readline.parse_and_bind('tab: complete')

O backend pode variar. Algumas plataformas usam GNU Readline; outras utilizam editline ou não oferecem o módulo. O código deve continuar funcionando mesmo sem autocompletar.

Completar nomes simples

Quando o texto não contém ponto, o completer procura nomes no namespace, em builtins e nas palavras-chave da linguagem.

namespace = {
    'processar_arquivo': processar_arquivo,
    'processar_fila': processar_fila,
}
completer = Completer(namespace)

Uma busca por proce pode sugerir as duas funções. Palavras como for, while e class também aparecem conforme o prefixo.

Completar atributos

Com um ponto, o módulo resolve o objeto à esquerda e usa dir() para encontrar atributos correspondentes.

import pathlib

completer = Completer({'pathlib': pathlib})
# sugestões para pathlib.Pa incluem Path

Esse comportamento melhora a descoberta de APIs, mas pode acionar lógica customizada. Objetos com __getattr__(), proxies remotos, ORMs e propriedades dinâmicas podem acessar rede, disco ou banco.

O risco de __getattr__()

A documentação afirma que funções não são avaliadas durante a resolução, mas chamadas a __getattr__() podem ocorrer. Considere um proxy que busca dados remotamente quando um atributo desconhecido é consultado.

class Proxy:
    def __getattr__(self, nome):
        registrar_acesso(nome)
        return carregar_remotamente(nome)

Autocompletar proxy.cl pode gerar uma consulta. Não exponha objetos com resolução perigosa em namespaces de consoles usados por terceiros.

Namespace explícito

Sem um namespace fornecido, Completer trabalha com o ambiente principal. Em ferramentas embutidas, passe um dicionário explícito para evitar sugestões acidentais de módulos, credenciais ou objetos internos.

namespace_publico = {
    'status': status_publico,
    'ajuda': ajuda,
    'versao': '3.0',
}
completer = Completer(namespace_publico)

Isso melhora a experiência e reduz exposição, mas não substitui autorização. Se o REPL executa Python real, o usuário pode encontrar outros caminhos de introspecção.

Coletar todas as sugestões

Para uma interface web ou editor, crie uma função que itera pelos estados até None.

def completar(completer, texto, limite=100):
    resultados = []
    for estado in range(limite):
        item = completer.complete(texto, estado)
        if item is None:
            break
        if item not in resultados:
            resultados.append(item)
    return resultados

O limite impede loops inesperados e evita respostas enormes. Também aplique tamanho máximo ao prefixo.

Integrar com InteractiveConsole

O módulo combina naturalmente com code no Python. O mesmo dicionário pode ser usado como namespace do interpretador e do completer.

import readline
from code import InteractiveConsole
from rlcompleter import Completer

namespace = {'status': mostrar_status}
readline.set_completer(Completer(namespace).complete)
readline.parse_and_bind('tab: complete')
InteractiveConsole(locals=namespace, local_exit=True).interact()

Se o console for local e confiável, isso cria uma experiência próxima ao interpretador padrão.

Integrar com cmd.Cmd

cmd.Cmd já possui seu próprio protocolo de conclusão para comandos e argumentos. Use rlcompleter quando uma ação específica precisa completar expressões Python, não para substituir todo o mecanismo do cmd no Python.

def complete_inspecionar(self, text, line, begidx, endidx):
    return completar(self.python_completer, text)

Antes de devolver atributos, verifique se o usuário pode inspecionar o objeto correspondente.

Filtrar atributos privados

Uma interface pode remover sugestões que começam com underscore.

def publicas(sugestoes):
    resultado = []
    for item in sugestoes:
        parte = item.rsplit('.', 1)[-1]
        if not parte.startswith('_'):
            resultado.append(item)
    return resultado

Esse filtro reduz ruído, mas não é uma barreira de segurança. Um usuário que executa código pode digitar o nome privado manualmente.

Ordenar e limitar resultados

Namespaces grandes podem produzir centenas de opções. Ordene, remova duplicados e devolva apenas as primeiras sugestões relevantes.

resultados = sorted(set(completar(completer, prefixo)))[:30]

Interfaces gráficas podem classificar nomes exatos primeiro, depois prefixos públicos e por último atributos privados autorizados.

Cache de sugestões

Em editores, o mesmo prefixo pode ser consultado repetidamente. Um cache curto reduz trabalho, mas precisa ser invalidado quando o namespace muda.

from functools import lru_cache

@lru_cache(maxsize=128)
def completar_cacheado(texto, versao_namespace):
    return tuple(completar(completer, texto))

Inclua uma versão do namespace na chave ou limpe o cache após imports, criação de variáveis e troca de contexto.

Autocompletar não valida código

Uma sugestão existente não garante que a expressão seja segura, correta ou autorizada. O completer apenas encontra nomes. A compilação e execução continuam sendo responsabilidades separadas.

Para detectar blocos incompletos em um REPL, use codeop. Para tokenizar comandos parecidos com shell, use o artigo existente sobre shlex.

Plataformas sem readline

A classe Completer pode ser usada mesmo quando readline não existe. Isso permite criar um widget próprio.

completer = Completer(namespace)
sugestoes = completar(completer, texto_digitado)

No Windows, bibliotecas alternativas podem fornecer edição de linha, mas a lógica de coleta continua independente.

Timeout e objetos lentos

O método não possui timeout interno. Se a resolução de atributos for lenta, a interface pode travar. Evite objetos com I/O e execute conclusões complexas em um worker isolado com prazo curto.

Não tente encerrar uma thread arbitrariamente. Prefira processos descartáveis quando o namespace contém objetos potencialmente bloqueantes.

Tratamento de exceções

Exceções levantadas durante a avaliação são capturadas e o módulo retorna None. Isso evita quebrar o prompt, mas pode esconder um problema operacional.

Para depuração, envolva o completer em uma camada que registre falhas de forma limitada, sem expor detalhes ao usuário.

Testes

Teste nomes simples, palavras-chave, atributos, namespace vazio, objetos com __getattr__(), exceções, duplicados e limites.

def test_completar_nome():
    c = Completer({'cliente': 1, 'classe': 2})
    itens = completar(c, 'cl')
    assert any('cliente' in item for item in itens)
    assert any('classe' in item for item in itens)

Inclua testes sem readline para garantir que a aplicação continua utilizável.

Erros frequentes

  • Expor o namespace inteiro sem necessidade.
  • Presumir que completar atributos não causa efeitos.
  • Usar nomes privados como controle de acesso.
  • Não limitar a quantidade de sugestões.
  • Manter cache após alterar o namespace.
  • Depender de GNU Readline em todas as plataformas.
  • Confundir sugestão com validação.

Boas práticas

  • Passe um namespace explícito.
  • Exponha objetos simples e sem I/O.
  • Limite prefixo, estados e resultados.
  • Filtre ruído sem tratar o filtro como segurança.
  • Invalide caches após mudanças.
  • Mantenha fallback sem autocompletar.
  • Teste proxies e atributos dinâmicos.

Conclusão

O rlcompleter no Python é uma forma simples de adicionar sugestões de identificadores e atributos a REPLs, consoles e editores. Ele funciona diretamente com readline, mas sua classe também pode alimentar interfaces próprias.

O principal cuidado está na resolução de atributos: __getattr__() pode executar lógica. Use namespaces controlados, objetos previsíveis, limites e isolamento quando necessário. Consulte a documentação oficial do rlcompleter e a documentação do readline.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026
    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026