fileinput no Python: leia vários arquivos

Publicado em: 07/08/2026
Tempo de leitura: 8 minutos
Teclado e fluxo de dados representando leitura de vários arquivos com fileinput no Python

Scripts de linha de comando frequentemente precisam processar uma sequência de arquivos como se todos formassem um único fluxo. Também é comum aceitar dados pela entrada padrão quando nenhum caminho é informado. O módulo fileinput no Python resolve esses dois casos com uma interface simples: ele percorre os arquivos listados em sys.argv, usa sys.stdin quando a lista está vazia e fornece informações como nome atual, número cumulativo da linha e posição dentro de cada arquivo.

Neste guia, você aprenderá a usar fileinput.input(), a classe FileInput, hooks para arquivos comprimidos, edição in-place com backup, encoding explícito e tratamento seguro de erros. O conteúdo complementa nossos artigos sobre pathlib, tempfile, shlex, filecmp e linecache.

Quando usar fileinput

O módulo é útil quando um programa deve receber zero, um ou vários arquivos e aplicar a mesma lógica linha por linha. Um filtro de texto, normalizador de logs, extrator de dados ou ferramenta de migração pode usar uma única iteração sem abrir cada caminho manualmente.

import fileinput

for linha in fileinput.input(encoding="utf-8"):
    processar(linha)

Por padrão, os nomes vêm de sys.argv[1:]. Se não houver nenhum, o módulo lê sys.stdin. Assim, o mesmo script pode funcionar com arquivos ou pipes.

Exemplo no terminal

python analisar.py app.log api.log
cat app.log | python analisar.py

No primeiro comando, as linhas vêm dos dois arquivos. No segundo, a entrada vem do pipe. Um nome igual a - também representa stdin.

Fornecer arquivos explicitamente

Você não precisa depender dos argumentos do processo.

arquivos = ["janeiro.csv", "fevereiro.csv"]

with fileinput.input(files=arquivos, encoding="utf-8") as entrada:
    for linha in entrada:
        processar(linha)

O contexto garante que o arquivo atual e a sequência sejam fechados mesmo se ocorrer uma exceção.

Uma string também é aceita

O parâmetro files pode receber um único nome ou uma sequência.

for linha in fileinput.input(files="dados.txt", encoding="utf-8"):
    print(linha, end="")

Use uma lista ou tupla quando a coleção for montada dinamicamente.

Quebras de linha são preservadas

As linhas mantêm o caractere de nova linha quando ele existe. A última linha de um arquivo pode não ter terminador.

for linha in fileinput.input(files="dados.txt", encoding="utf-8"):
    print(repr(linha))

Não remova espaços indiscriminadamente com strip() se eles fizerem parte dos dados. Para remover somente a quebra final, use rstrip("\r\n") com consciência de que isso remove todos os terminadores correspondentes.

Descobrir o arquivo atual

fileinput.filename() devolve o nome da fonte que produziu a linha mais recente.

for linha in fileinput.input(files=arquivos, encoding="utf-8"):
    print(fileinput.filename(), linha, end="")

Antes de ler a primeira linha, o retorno é None. Funções globais como essa dependem de uma instância ativa criada por fileinput.input().

Número cumulativo da linha

lineno() conta todas as linhas lidas desde o início da sequência.

for linha in fileinput.input(files=arquivos, encoding="utf-8"):
    print(fileinput.lineno(), linha, end="")

Se o primeiro arquivo tem 100 linhas, a primeira linha do segundo terá número cumulativo 101.

Número dentro do arquivo

filelineno() reinicia a contagem em cada arquivo.

for linha in fileinput.input(files=arquivos, encoding="utf-8"):
    print(
        fileinput.filename(),
        fileinput.filelineno(),
        linha,
        end="",
    )

Isso é útil para mensagens de erro que precisam apontar o caminho e a linha local.

Identificar a primeira linha

isfirstline() indica se a linha atual é a primeira do arquivo.

for linha in fileinput.input(files=arquivos, encoding="utf-8"):
    if fileinput.isfirstline():
        print(f"--- {fileinput.filename()} ---")
    print(linha, end="")

O método ajuda a tratar cabeçalhos ou imprimir separadores.

Identificar stdin

isstdin() informa se a última linha veio da entrada padrão.

if fileinput.isstdin():
    origem = "stdin"
else:
    origem = fileinput.filename()

Se stdin aparece mais de uma vez na lista, usos posteriores normalmente não produzem novas linhas, porque o fluxo já foi consumido.

Pular o restante do arquivo

nextfile() fecha o arquivo atual e avança para o próximo. Linhas ignoradas não entram na contagem cumulativa.

for linha in fileinput.input(files=arquivos, encoding="utf-8"):
    if linha.startswith("FIM"):
        fileinput.nextfile()
        continue
    processar(linha)

A função não pode pular o primeiro arquivo antes da primeira linha ser lida. O nome atual só muda quando uma linha do próximo arquivo é obtida.

Usar a classe FileInput

A classe expõe as mesmas operações sem depender das funções globais.

from fileinput import FileInput

with FileInput(files=arquivos, encoding="utf-8") as entrada:
    for linha in entrada:
        print(
            entrada.filename(),
            entrada.filelineno(),
            linha,
            end="",
        )

Essa forma é melhor quando uma aplicação precisa de várias sequências independentes ou deseja passar o objeto para outra função.

Evitar estado global concorrente

fileinput.input() cria um estado global utilizado por funções como filename(). Uma segunda chamada enquanto a primeira está ativa gera conflito. Em bibliotecas, servidores e código concorrente, prefira instâncias explícitas de FileInput.

Encoding e erros

Desde versões modernas do Python, encoding e errors podem ser passados diretamente.

with fileinput.input(
    files=arquivos,
    encoding="utf-8",
    errors="strict",
) as entrada:
    for linha in entrada:
        processar(linha)

Use strict quando dados inválidos devem interromper o processo. Estratégias como replace ou surrogateescape precisam ser escolhidas conscientemente, porque podem alterar ou preservar bytes problemáticos de formas diferentes.

Modo binário

FileInput aceita mode="r" ou mode="rb".

with fileinput.FileInput(files=arquivos, mode="rb") as entrada:
    for linha in entrada:
        processar_bytes(linha)

No modo binário, as linhas são objetos bytes. Não forneça encoding nessa situação.

Erros de I/O

Ao contrário de linecache, fileinput propaga OSError quando não consegue abrir ou ler uma fonte.

try:
    with fileinput.input(files=arquivos, encoding="utf-8") as entrada:
        for linha in entrada:
            processar(linha)
except OSError as erro:
    print(f"falha de leitura: {erro}")

Em um lote, decida se a falha de um arquivo deve interromper tudo ou ser registrada para continuação. Fileinput não oferece uma política automática de “ignorar erros”.

Arquivos vazios

Um arquivo vazio é aberto e fechado sem produzir linhas. Sua presença pode passar despercebida. Se arquivos vazios são inválidos, valide o tamanho ou mantenha um registro dos caminhos processados.

Abrir gzip e bzip2

hook_compressed() abre automaticamente arquivos .gz e .bz2.

with fileinput.FileInput(
    files=["app.log", "app.log.gz", "antigo.log.bz2"],
    openhook=fileinput.hook_compressed,
    encoding="utf-8",
) as entrada:
    for linha in entrada:
        processar(linha)

Arquivos com outras extensões são abertos normalmente. A detecção usa o sufixo, não a assinatura real do conteúdo.

Hooks personalizados

Um openhook recebe nome e modo e deve devolver um objeto de arquivo compatível. Quando encoding e errors são informados, o hook também os recebe como keywords.

def abrir_validado(filename, mode, *, encoding=None, errors=None):
    caminho = Path(filename).resolve()
    if caminho.suffix not in {".txt", ".log"}:
        raise ValueError("extensão não permitida")
    return open(caminho, mode, encoding=encoding, errors=errors)

with fileinput.FileInput(
    files=arquivos,
    openhook=abrir_validado,
    encoding="utf-8",
) as entrada:
    for linha in entrada:
        processar(linha)

Não use openhook junto com edição in-place.

Edição in-place

Com inplace=True, cada arquivo é movido para um backup e sys.stdout passa a apontar para o arquivo original. Tudo que o script imprime substitui o conteúdo.

for linha in fileinput.input(
    files=["config.txt"],
    inplace=True,
    backup=".bak",
    encoding="utf-8",
):
    print(linha.replace("antigo", "novo"), end="")

Ao terminar, config.txt contém o texto transformado e config.txt.bak preserva o original.

Riscos da edição in-place

A operação é poderosa e pode destruir dados quando o programa imprime menos conteúdo, falha no meio ou escolhe o arquivo errado. Teste primeiro sem inplace, mantenha backup, processe cópias e verifique espaço em disco.

A documentação oficial de fileinput informa que um backup existente com o mesmo nome pode ser substituído silenciosamente. Use uma estratégia própria de nomes quando isso for inaceitável.

Backup padrão

Quando inplace=True e nenhum sufixo permanente é definido, um backup temporário é usado e removido após o fechamento. Para mudanças importantes, especifique uma extensão e preserve o arquivo.

Stdout durante a reescrita

Mensagens de progresso impressas normalmente também seriam gravadas no arquivo. Envie diagnósticos para stderr.

import sys

print("processando", fileinput.filename(), file=sys.stderr)

Separe claramente a saída transformada das mensagens operacionais.

In-place não funciona com stdin

A edição no lugar é desativada para entrada padrão porque não existe um arquivo original que possa ser substituído. Um filtro que recebe pipe deve escrever sua saída normalmente e deixar o chamador decidir o destino.

Transações mais seguras

Para dados importantes, uma estratégia com arquivo temporário é mais controlável: escreva em outro caminho, faça flush(), sincronize se necessário, valide o resultado e substitua o original com os.replace().

Essa abordagem permite manter permissões, lidar com erros e criar backups versionados explicitamente.

Não misturar iteração e acesso aleatório

FileInput é uma sequência estritamente linear. Não misture iteração e readline() de formas imprevisíveis, nem espere acesso por índice. Para acesso aleatório por número de linha, use linecache ou leia o arquivo em uma estrutura apropriada.

Segurança com argumentos

Se os nomes vêm de usuários, valide uma raiz permitida e resolva symlinks.

BASE = Path("/srv/importacoes").resolve()

def caminho_permitido(nome):
    caminho = (BASE / nome).resolve()
    if caminho != BASE and BASE not in caminho.parents:
        raise ValueError("caminho fora da área permitida")
    return caminho

Também limite tamanho, quantidade de arquivos e formatos comprimidos para evitar consumo excessivo de recursos.

Arquivos comprimidos hostis

Um arquivo pequeno pode expandir para muitos gigabytes. Aplique limites de bytes, tempo e linhas em entradas desconhecidas. hook_compressed() facilita a abertura, mas não implementa proteção contra bombas de compressão.

Testes

def test_multiplos_arquivos(tmp_path):
    a = tmp_path / "a.txt"
    b = tmp_path / "b.txt"
    a.write_text("um\ndois\n", encoding="utf-8")
    b.write_text("três\n", encoding="utf-8")

    with fileinput.FileInput(files=[a, b], encoding="utf-8") as entrada:
        linhas = list(entrada)

    assert linhas == ["um\n", "dois\n", "três\n"]

Teste arquivos vazios, última linha sem quebra, encoding inválido, stdin, arquivos comprimidos e falhas durante reescrita.

fileinput versus open()

Use open() para um único arquivo e controle explícito. Use fileinput quando a principal abstração é uma sequência contínua de várias fontes, especialmente em ferramentas de terminal.

Erros frequentes

  • Depender acidentalmente de sys.argv.
  • Esquecer de declarar encoding.
  • Abrir duas sequências globais ao mesmo tempo.
  • Usar strip() e remover espaços significativos.
  • Imprimir logs em stdout durante edição in-place.
  • Reescrever arquivos sem backup permanente.
  • Presumir que stdin pode ser lido várias vezes.
  • Aceitar arquivos comprimidos sem limites.

Boas práticas

  • Use contexto with.
  • Prefira FileInput explícito em bibliotecas.
  • Declare encoding e política de erros.
  • Envie logs para stderr.
  • Preserve backups em operações destrutivas.
  • Valide caminhos e tamanhos externos.
  • Teste última linha e arquivos vazios.
  • Use substituição atômica para dados críticos.

Conclusão

O módulo fileinput no Python simplifica filtros que recebem vários arquivos ou stdin, mantendo informações úteis de origem e numeração. Ele também oferece hooks para compressão e uma edição in-place conveniente.

A simplicidade exige disciplina: evite estado global em código complexo, defina encoding, trate OSError e considere qualquer reescrita como operação destrutiva. Com backups, validação e testes, fileinput é uma excelente base para utilitários de linha de comando claros e compactos.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Documento e caixa de entrada representando caixas de e-mail com mailbox no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    mailbox no Python: caixas de e-mail

    Aprenda mailbox no Python para ler, criar e migrar caixas Maildir, mbox e MH com locking, mensagens, flags e tratamento

    Ler mais

    Tempo de leitura: 6 minutos
    12/08/2026
    Editor de texto representando formatação com textwrap no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap no Python: formate textos

    Aprenda textwrap no Python para quebrar, preencher, encurtar, indentar e remover recuos de textos com controle de largura e espaços.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Pasta e lupa representando filtros de nomes com fnmatch no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch no Python: filtre nomes de arquivos

    Aprenda fnmatch no Python para filtrar nomes de arquivos com curingas, controlar maiúsculas, excluir padrões e evitar confundir glob com

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor com dados binários representando arrays numéricos compactos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    array no Python: números compactos

    Aprenda array no Python para armazenar números compactos, manipular bytes, arquivos binários e buffers com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Círculo cromático representando conversões RGB, HSV e HLS com colorsys no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    colorsys no Python: RGB, HSV e HLS

    Aprenda colorsys no Python para converter cores entre RGB, HSV, HLS e YIQ, gerar paletas e evitar erros com escalas

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026
    Ícone de configuração representando arquivos plist com plistlib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib: leia e grave arquivos plist

    Aprenda plistlib no Python para ler e gravar arquivos plist XML e binários, validar dados e integrar configurações Apple com

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026