>_ josetilabs.com
← blog

10 out 2026 · python, desempenho, desenvolvimento · 4 min

Dez imports custam 100 ms na partida do seu script Python

Um script que importa dez módulos da biblioteca padrão leva 102 ms para chegar à primeira linha útil. Com a mesma lista declarada como import preguiçoso, 14 ms. A diferença é a palavra lazy na frente de cada import.

Isso existe desde 9 de outubro, quando o Python 3.15 saiu com o PEP 810 implementado. A sintaxe é nova e explícita: você escreve lazy import asyncio e o módulo só é carregado quando alguém o usa pela primeira vez. O nome da operação na proposta é reificação, e o efeito prático é que a partida do programa deixa de pagar por código que talvez nunca rode.

O que medi

Compilei o 3.14.8 e o 3.15.0 com o mesmo compilador e as mesmas flags, e rodei dois scripts idênticos em conteúdo. Um importa dez módulos da biblioteca padrão no jeito antigo, o outro declara os mesmos dez com lazy import e não os usa. Sete execuções de cada, menor tempo:

script 3.14.8 3.15.0
import comum, dez módulos 103 ms 100 ms
lazy import, mesmos dez módulos erro de sintaxe 14 ms

O 3.14 nem aceita a sintaxe, o que é justo: import preguiçoso é recurso de 3.15. O número que interessa é o de baixo, 14 ms, e ele é sete vezes menor que a partida comum. A contagem de módulos carregados explica: o script com imports comuns terminou com 230 módulos em sys.modules, o preguiçoso terminou com 32.

Também medi o custo individual de cada import, num interpretador novo a cada linha:

módulo custo de importar
asyncio 38,7 ms
urllib.request 28,6 ms
unittest 24,2 ms
logging.config 22,2 ms
email.message 14,3 ms
tarfile 10,9 ms
inspect 10,0 ms
statistics 9,4 ms
ssl 9,2 ms
json 7,2 ms
argparse 7,2 ms
re 5,5 ms
sqlite3 3,9 ms

Esses números não somam os 100 ms do script completo, porque vários módulos compartilham dependências e o custo aparece repetido em cada linha. A tabela serve para escolher candidato, não para somar orçamento.

Onde isso rende

CLI é o caso que salta. Ferramenta de linha de comando costuma ter um caminho rápido, do tipo --version ou --help, e um caminho pesado que faz o trabalho. O caminho rápido paga a importação de tudo e sai em 100 ms quando poderia sair em 15. Em servidor sem estado, com partida a frio por requisição, a mesma conta se repete multiplicada por carga.

python
# antes
import argparse, asyncio, sqlite3, unittest

# depois, em Python 3.15
lazy import argparse, asyncio, sqlite3, unittest

Para escolher o que deixar preguiçoso, meça antes de mexer:

bash
python3.15 -X importtime seu_cli.py 2> tempos.txt
sort -k2 -nr tempos.txt | head -15

A saída lista cada import com o tempo acumulado. Os três primeiros da lista que o caminho rápido não usa são a resposta.

O que muda de comportamento

Import preguiçoso move o momento do erro, e isso tem consequência. Se o módulo está faltando, o ImportError aparece no primeiro uso, não na primeira linha do programa. Para quem escreve script de infraestrutura, isso muda o que o log mostra quando a dependência some da máquina.

Efeito colateral de import também atrasa. Módulo que configura log, registra plugin ou abre conexão ao ser importado passa a fazer isso no meio da execução, e o lugar onde isso acontece deixa de ser previsível. Módulo com efeito no import é candidato ruim para a lista.

A proposta trata os dois pontos com um mecanismo de filtro e um modo global, que aplicam a regra sem mudar o código. É mais poderoso e mais arriscado, porque passa a valer para biblioteca de terceiro que não foi escrita pensando nisso. Começar pelos imports que você mesmo controla é a versão chata que funciona.

Ressalva: a medição é de dois interpretadores compilados localmente, com a lista que eu escolhi, em sete execuções. O ganho depende do que está sendo importado e de quanto código do caminho rápido depende disso. import time não tem o que ganhar.

Minha opinião é que a mudança vale mais pelo diagnóstico que ela força do que pelo ganho em si. Todo CLI que eu escrevi carrega coisa que não usa, e nunca medi porque a partida parecia instantânea. Cem milissegundos por vez, multiplicados por todas as chamadas de um script de automação, viram alguns segundos de espera que ninguém atribuía à importação. É a mesma escolha de sempre, comprar tempo de partida com disciplina de código, e ela aparece em qualquer runtime quando você troca recurso por latência ou paga por pausas que ninguém vê.

Leia também

// Por e-mail

Os textos publicados aqui também vão por e-mail. O envio ainda não começou: quem deixar o endereço agora entra na primeira lista.

Guardo só o seu e-mail, a data e o registro desta autorização. Sem cookies, sem rastreador e nada compartilhado com terceiros. Detalhes na política de privacidade.