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

    Editor de código com linhas numeradas representando o módulo linecache no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    linecache no Python: leia linhas por número

    Aprenda linecache no Python para ler linhas por número, usar cache, atualizar arquivos modificados e integrar fontes com traceback e

    Ler mais

    Tempo de leitura: 7 minutos
    07/08/2026
    Dados binários representando serialização interna com marshal no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    marshal no Python: serialização interna

    Aprenda marshal no Python para serializar tipos internos, controlar versões e bloquear objetos de código com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    06/08/2026
    Monitor com código binário representando personalização de pickle com copyreg no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    copyreg no Python: personalize o pickle

    Aprenda copyreg no Python para registrar funções de redução, personalizar pickle e preservar compatibilidade de objetos.

    Ler mais

    Tempo de leitura: 6 minutos
    06/08/2026
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    functools.partial no Python: guia prático

    Aprenda functools.partial no Python para fixar argumentos, adaptar callbacks e criar funções especializadas com clareza.

    Ler mais

    Tempo de leitura: 6 minutos
    06/08/2026
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    filecmp no Python: compare arquivos e pastas

    Aprenda filecmp no Python para comparar arquivos e pastas, usar shallow, dircmp, cmpfiles, cache e hashes de integridade.

    Ler mais

    Tempo de leitura: 7 minutos
    03/08/2026
    Terminal de comandos representando parsing seguro com shlex no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    shlex no Python: comandos e argumentos seguros

    Aprenda shlex no Python para separar comandos, tratar aspas, usar quote e join e reduzir riscos de injeção ao executar

    Ler mais

    Tempo de leitura: 7 minutos
    02/08/2026