Como atualizar para o Python 3.15: instalar com uv, usar imports preguiçosos (lazy imports) e checar seus pacotes
Atualizado em

Resposta curta: o Python 3.15.0 foi lançado em 9 de outubro de 2026. Se você usa o uv (opens in a new tab), atualize o uv primeiro e depois instale:
uv self update
uv python install 3.15Em seguida, crie um projeto de teste e experimente suas dependências reais antes de migrar qualquer coisa importante:
uv init --python 3.15 py315-test
cd py315-test
uv add numpy pandas scikit-learn matplotlibO stack científico principal já instala a partir de wheels prontos. PyTorch e TensorFlow não instalam. O DuckDB compila a partir do código-fonte. Se o seu projeto depende de algum deles, fique no 3.14 por enquanto (uv python pin 3.14).
O recurso que justifica a atualização são os imports preguiçosos (lazy imports). Uma única palavra-chave, lazy import pandas as pd, levou o caminho --help de um script de teste de 2.7 segundos para 0.01 segundo.
O que foi testado: tudo o que aparece como "testado" abaixo foi executado em 11 de outubro de 2026, em um Apple M4 Max (macOS), com uv 0.13.0 e CPython 3.15.0 / 3.15.0t instalados via
uv python install. O comportamento no Windows e no Linux, o instalador do python.org, o pyenv e o conda vêm da documentação oficial e não foram testados.
O que muda no 3.15 e você vai notar
O changelog é longo. Se você escreve scripts de dados ou CLIs, estas são as cinco mudanças que vão aparecer no seu dia a dia:
| Mudança | O que significa para você | O que fazer |
|---|---|---|
| Lazy imports (PEP 810) | lazy import x adia o carregamento até o primeiro uso | Use em CLIs, scripts e apps que demoram para iniciar |
| UTF-8 é a codificação padrão (PEP 686) | open("file.txt") agora lê e grava em UTF-8 em qualquer sistema | No Windows, com arquivos cp1252 / cp932 / GBK: passe encoding= explicitamente |
| uv 0.13 usa o 3.15 por padrão | Projetos novos do uv sem versão fixada recebem o 3.15 automaticamente | Fixe o 3.14 onde suas dependências ainda não estão prontas |
| O build free-threaded ganha ABI estável (PEP 803) | python3.15t executa threads em paralelo, mas a maioria dos pacotes ainda não publica wheels com ABI estável para ele | Espere builds a partir do código-fonte no 3.15t |
Built-ins frozendict e sentinel, pacote profiling | Novos tipos nativos e o profiler por amostragem Tachyon | Opcional; nada quebra se você ignorar |
A lista completa está no What's New in Python 3.15 oficial (opens in a new tab). O restante deste guia cobre as tarefas: instalar, checar compatibilidade, usar lazy imports, lidar com a mudança de codificação e decidir sobre o free-threading.
- Como atualizar para o Python 3.15: instalar com uv, usar imports preguiçosos (lazy imports) e checar seus pacotes
- Tutorial de Claude Code Mods: como criar, testar e instalar seu primeiro mod, com 15 exemplos da comunidade
- GPT Image 2.5: como usar, Flare vs Sunburst e preços da API
- Como usar o DeepSeek Harness: instalar, configurar e rodar seu primeiro agente
- Runcell Science: alternativa open source ao Claude Science para pesquisa com IA
- Como impedir o Mac de dormir: mantenha Codex, Claude Code e agentes de IA rodando
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot: qual stack de agentes de IA você deve escolher em 2026?
- Como o Claude Code analisa notebooks Jupyter em Data Science: capacidade real, limites e alternativa melhor
- Claude Code Routines: rotinas e cron jobs para agentes de IA
- Claude Code Desktop: como ativar Bypass permissions
- Como Construir Dois Agentes Python com o Protocolo A2A do Google - Tutorial Passo a Passo
- Top 10 bibliotecas de visualização de dados em Python em 2025
Passo 1: instalar o Python 3.15
Com uv (testado)
Atualize o uv antes de instalar. Pular esta etapa é o erro mais fácil de cometer nesta semana. Um uv antigo só conhece as versões alpha. No uv 0.9.25 que já tínhamos instalado, uv python list 3.15 mostrava apenas cpython-3.15.0a4. Rodar uv python install 3.15 ali instalaria uma alpha, não a versão final.
uv self update # needs 0.13.0 or newer
uv --version
uv python install 3.15O uv 0.13.0 instalou o build normal e o free-threaded em 24.8 segundos:
uv python install 3.15 3.15tInstalled 2 versions in 24.83s
+ cpython-3.15.0+freethreaded-macos-aarch64-none (python3.15t)
+ cpython-3.15.0-macos-aarch64-none (python3.15)Se você instalou o uv com Homebrew, pip ou pipx, uv self update não funciona. Atualize do mesmo jeito que instalou (brew upgrade uv, pipx upgrade uv).
O uv 0.13 também muda o padrão. As notas de versão do uv 0.13.0 (opens in a new tab) dizem que uv python install sem versão agora baixa o 3.15. Um uv venv ou uvx python novo baixa o 3.15 se não houver um Python compatível instalado. Instalações existentes continuam sendo usadas. Para manter um projeto no 3.14, registre isso:
uv python pin 3.14Esse comando grava o arquivo .python-version, que o uv lê sempre que roda naquela pasta.
Outras formas (da documentação oficial, não testadas aqui)
- Instalador do python.org (Windows, macOS): baixe o 3.15.0 em python.org/downloads (opens in a new tab). Segundo as notas de versão, o instalador oficial para macOS agora instala o suporte a free-threading por padrão, e os binários de 64 bits para Windows usam o novo interpretador com tail calls.
- pyenv:
pyenv updatee depoispyenv install 3.15.0. Espere até que a sua versão do pyenv liste o 3.15.0. - conda: crie um ambiente com
python=3.15quando o conda-forge publicar a versão. Confira antes de planejar uma migração em torno dele.
Se você quer a visão geral de como trocar de versão do Python em cada sistema, nosso guia de como atualizar o Python e a comparação de gerenciadores de versão do Python continuam válidos. Esta página cobre o que é específico do 3.15.
Passo 2: checar se seus pacotes instalam
É este passo que decide se você pode atualizar hoje. Criamos um projeto 3.15 limpo, instalamos um stack típico de ciência de dados e consultamos o PyPI para os pacotes mais procurados.
Tabela de compatibilidade (testada em 11 de outubro de 2026)
| Pacote (versão) | Python 3.15 | Python 3.15t (free-threaded) | Observações |
|---|---|---|---|
| numpy 2.5.4 | Wheel | Wheel | |
| pandas 3.0.6 | Wheel | Wheel | |
| scipy 1.18.1 | Wheel | Wheel | |
| scikit-learn 1.9.1 | Wheel | Wheel | |
| matplotlib 3.11.2 | Wheel | Wheel | |
| pyarrow 26.0.0 | Wheel | Wheel | |
| polars 2.0.0 | Wheel (abi3) | Compila do código-fonte | O runtime só publica wheels cp310-abi3, que o Python free-threaded não consegue usar. O build em Rust levou 6 min 51 s |
| ipykernel 9.17.1 (pyzmq, psutil, debugpy) | Wheel | Não testado | Kernels do Jupyter funcionam no 3.15 |
| duckdb 1.5.6 | Compila do código-fonte | Não testado | Os wheels param no cp314. O build em C++ levou cerca de 2.5 min |
| pygwalker 0.5.0.1 | Funciona | Não testado | Depende do duckdb, então herda o build a partir do código-fonte |
| torch 2.14.1 | Não instala | Não instala | Só há wheels de cp310 a cp314 e cp314t |
| tensorflow 2.21.0 | Não instala | Não instala | Só há wheels de cp310 a cp313 |
Instalar numpy, pandas, scipy, scikit-learn, matplotlib, pyarrow e polars levou 71 segundos no 3.15, com download incluído e sem compilação. O mesmo conjunto no 3.15t levou 6 minutos e 51 segundos, quase todo esse tempo compilando o Polars.
Quando um pacote não tem wheel, o uv diz exatamente o motivo. Veja como fica o PyTorch no 3.15:
hint: You require CPython 3.15 (`cp315`), but we only found wheels for `torch`
(v2.14.1) with the following Python ABI tags: `cp310`, `cp311`, `cp312`, `cp313`, `cp314`, `cp314t`Cheque seu próprio projeto em um minuto
Você não precisa instalar nada para descobrir. Faça um dry run contra um ambiente 3.15:
uv venv --python 3.15 .venv315
uv pip install --dry-run --python .venv315/bin/python -r requirements.txtSe resolver, está tudo certo. Se aparecer a dica cp315 acima, esse pacote é o seu bloqueio.
Um build a partir do código-fonte não é uma falha, mas é lento e exige um compilador (Rust para o Polars, C++ para o DuckDB). No CI, isso pode transformar um job de um minuto em um de dez. Fixe o 3.14 no CI até os wheels saírem.
Passo 3: usar lazy imports para scripts iniciarem mais rápido
Na minha opinião, os imports preguiçosos são o melhor motivo para migrar para o 3.15. O problema que eles resolvem é conhecido.
Um script de linha de comando costuma importar tudo no topo. Até my_tool.py --help paga o custo completo de carregar pandas, matplotlib e scikit-learn, mesmo sem usar nenhum deles.
Antes e depois (testado)
A versão com imports imediatos (eager):
import sys
import pandas as pd
import matplotlib.pyplot as plt
import sklearn.linear_model
if len(sys.argv) > 1 and sys.argv[1] == "--help":
print("usage: tool [--help] file.csv")
sys.exit(0)A versão preguiçosa só acrescenta a palavra-chave lazy:
import sys
lazy import pandas as pd
lazy import matplotlib.pyplot as plt
lazy from sklearn import linear_model
if len(sys.argv) > 1 and sys.argv[1] == "--help":
print("usage: tool [--help] file.csv")
sys.exit(0)
df = pd.DataFrame({"x": [1, 2, 3], "y": [2, 4, 6]})
model = linear_model.LinearRegression().fit(df[["x"]], df["y"])
print(model.coef_)Resultados na nossa máquina, cinco execuções de python script.py --help para cada versão:
| Versão | Tempo | Linhas em -X importtime |
|---|---|---|
| Imports imediatos | 2.69 a 2.74 s | 1,747 |
lazy import | 0.01 s | 27 |
O caminho completo continua funcionando: a versão preguiçosa ajustou a regressão e imprimiu 2.0. O pandas é carregado na linha que usa pd pela primeira vez.
Seus números absolutos vão ser diferentes. Neste ambiente, só import sklearn.linear_model levou 2.2 s e import pandas levou 0.86 s. O padrão vale para qualquer ramo do programa que não toque em uma biblioteca pesada.
Veja o que os lazy imports estão fazendo
Um nome preguiçoso é um proxy até você usá-lo. Dá para ver isso:
import sys
lazy import json
print(type(globals()["json"])) # <class 'lazy_import'>
print("json" in sys.modules) # False
json.dumps(1)
print(type(globals()["json"]), "json" in sys.modules) # <class 'module'> TruePara descobrir quais imports são lentos, rode python -X importtime your_script.py 2> imports.log e ordene pela segunda coluna.
Três lugares em que lazy dá SyntaxError (testado)
lazy só funciona no nível do módulo. Encontramos os três erros abaixo:
| Onde | Mensagem de erro |
|---|---|
| Dentro de uma função | SyntaxError: lazy import not allowed inside functions |
Dentro de try / except | SyntaxError: lazy import not allowed inside try/except blocks |
| Import com asterisco | SyntaxError: lazy from ... import * is not allowed |
A regra do try/except é a que mais pesa. Um código como try: import ujson as json except ImportError: import json não pode virar lazy. Mantenha o fallback imediato ou mova-o para um módulo pequeno que você importa de forma preguiçosa.
A documentação oficial acrescenta que corpos de classe e imports from __future__ também não podem ser lazy.
Os erros passam para o primeiro uso
Um módulo inexistente não falha mais no topo do arquivo:
lazy import not_a_real_module
print("defined ok") # this prints
not_a_real_module.x # ModuleNotFoundError is raised hereIsso é prático para dependências opcionais. Mas também significa que um erro de digitação em um import pode ficar escondido até um caminho de código raramente usado rodar. Mantenha pelo menos um teste que exercite cada lazy import.
Deixar tudo lazy sem editar o código
Você pode ativar lazy imports no programa inteiro pela linha de comando:
python -X lazy_imports=all my_tool.py --help
# or
PYTHON_LAZY_IMPORTS=all python my_tool.py --helpNosso script eager, sem nenhuma alteração, caiu para 0.01 s dessa forma. Cuidado, porém, com módulos que fazem trabalho no momento do import. Criamos um módulo de plugin minúsculo que imprime uma mensagem e se registra ao ser importado. Com lazy_imports=all, o registro nunca aconteceu, porque o programa nunca tocou no nome do módulo:
normal: plugin registered / main done
all: main doneBibliotecas que registram plugins, codecs ou backends do matplotlib no import podem quebrar do mesmo jeito. Use =all para medir o ganho possível e depois adicione lazy à mão nos imports que você sabe que são seguros. Para um controle mais fino, a documentação descreve sys.set_lazy_imports_filter().
Suportar 3.14 e 3.15 no mesmo arquivo
A palavra-chave lazy é erro de sintaxe no 3.14 e anteriores. Se o seu código precisa rodar nos dois, use a lista __lazy_modules__ no nível do módulo. Versões antigas a ignoram, e o 3.15 trata esses imports como lazy:
__lazy_modules__ = ["pandas"]
import sys
import pandas as pd # lazy on 3.15, eager on 3.14
print("pandas" in sys.modules) # False on 3.15 until pd is usedConfirmamos que, com esse padrão, o pandas ficou fora de sys.modules no 3.15.
Passo 4: lidar com o UTF-8 como padrão
No 3.15, open() sem o argumento encoding usa UTF-8 em todas as plataformas. Confirmamos sys.flags.utf8_mode == 1 por padrão e 0 com PYTHONUTF8=0.
No macOS e no Linux isso quase não muda nada. No Windows, muda o comportamento de qualquer código que lê arquivos legados sem informar a codificação: exportações CSV do Excel em cp1252, arquivos japoneses em Shift-JIS (cp932) ou arquivos chineses em GBK. Essas leituras agora podem gerar UnicodeDecodeError ou texto embaralhado.
A solução é ser explícito:
import pandas as pd
df = pd.read_csv("export.csv", encoding="cp932") # Japanese Excel export
with open("legacy.txt", encoding="locale") as f: # old behavior: system locale
text = f.read()Para encontrar o código afetado antes de atualizar, rode seus testes no Python atual com -X warn_default_encoding. Para voltar temporariamente ao comportamento antigo, defina PYTHONUTF8=0.
Passo 5: decidir sobre o build free-threaded (3.15t)
O Python free-threaded remove o GIL, então threads em Python puro podem usar vários núcleos de CPU. Rodamos um loop pesado de CPU quatro vezes, primeiro em sequência e depois em quatro threads:
| Build | Sequencial | 4 threads | Aceleração |
|---|---|---|---|
| Python 3.15 | 0.72 s | 0.71 s | 1.0× |
| Python 3.15t | 0.65 s | 0.19 s | 3.4× |
O GIL continuou desligado depois de importar numpy, pandas, scikit-learn, polars, matplotlib e pyarrow (sys._is_gil_enabled() retornou False).
Use o 3.15t se você roda código Python puro pesado de CPU em threads e suas dependências têm wheels cp315t. Deixe de lado se você depende de Polars, DuckDB ou bibliotecas de deep learning. Deixe de lado também se o trabalho pesado já roda dentro do NumPy ou do pandas, que liberam o GIL por conta própria.
Vale atualizar agora?
| Sua situação | Recomendação |
|---|---|
| Scripts, CLIs e automação com o stack numpy / pandas / sklearn | Atualize. Os lazy imports são um ganho real |
| Notebooks Jupyter para análise | Atualize em um ambiente novo; mantenha o kernel antigo por algumas semanas |
| Projetos com PyTorch ou TensorFlow | Fique no 3.14 (uv python pin 3.14) |
| DuckDB ou Polars no 3.15t em CI | Espere os wheels ou aceite o tempo de compilação e um compilador no CI |
| Código Windows que lê arquivos com codificação legada | Adicione encoding= explícito primeiro e depois atualize |
Usando o 3.15 no Jupyter
O ipykernel instala e funciona no 3.15. Para registrar um kernel 3.15 a partir de um projeto uv:
uv add ipykernel
uv run python -m ipykernel install --user --name py315 --display-name "Python 3.15"Se você trabalha com notebooks, o RunCell (opens in a new tab) roda como um agente de IA dentro do Jupyter e enxerga o estado do kernel ao vivo. Isso ajuda a testar se um notebook existente ainda roda no kernel novo. O PyGWalker (opens in a new tab) também funciona no 3.15 (testado: pyg.to_html() renderizou um DataFrame), com a compilação do DuckDB mencionada acima.
Solução de problemas
| Sintoma | Causa | Solução |
|---|---|---|
uv python install 3.15 instala 3.15.0a4 | O uv é anterior ao 0.13 | uv self update, ou atualize pelo Homebrew / pipx |
No solution found … no wheels with a matching Python ABI tag (cp315) | O pacote ainda não tem wheel para 3.15 (torch, tensorflow) | uv python pin 3.14 nesse projeto |
| A instalação trava por minutos no duckdb ou no polars-runtime | Build a partir do código-fonte, porque não existe wheel compatível | Espere (exige compilador C++ ou Rust) ou use 3.14 / o 3.15 normal no lugar do 3.15t |
SyntaxError: lazy import not allowed … | lazy dentro de função, try ou classe | Mova o import para o nível do módulo ou mantenha-o eager |
| Um plugin ou backend para de se registrar | -X lazy_imports=all pulou um import com efeitos colaterais | Remova o =all; use lazy só em imports escolhidos |
UnicodeDecodeError no Windows depois de atualizar | UTF-8 agora é a codificação padrão | Passe encoding="cp1252" / "cp932" / "gbk" ou encoding="locale" |
| Projeto uv novo cai no 3.15 sem você esperar | O uv 0.13 mudou o padrão | uv python pin 3.14 |
SyntaxWarning: 'return' in a 'finally' block vindo de uma dependência | A biblioteca tem código antigo sinalizado pelo Python mais novo | Inofensivo; vem da biblioteca, não do seu código |
Perguntas frequentes
Quando o Python 3.15 foi lançado? O Python 3.15.0 foi lançado em 9 de outubro de 2026.
Como instalar o Python 3.15 com uv? Atualize o uv para a versão 0.13.0 ou mais nova e rode uv python install 3.15. Versões antigas do uv só conhecem as builds alpha do 3.15.
O pandas funciona no Python 3.15? Sim. O pandas 3.0.6 publica wheels cp315 e cp315t, assim como numpy, scipy, scikit-learn, matplotlib e pyarrow.
O PyTorch suporta o Python 3.15? Ainda não. Em 11 de outubro de 2026, o torch 2.14.1 só tem wheels até cp314 e cp314t, então não instala no 3.15.
O que são lazy imports no Python 3.15? Escrever lazy import module faz o Python criar um proxy leve e carregar o módulo só quando o nome é usado pela primeira vez. Isso reduz o tempo de inicialização nos caminhos de código que nunca tocam no módulo.
Dá para usar lazy imports e continuar suportando o Python 3.14? Sim. Defina __lazy_modules__ = ["module_name"] no topo do módulo. O Python 3.15 trata esses imports como lazy, e as versões antigas ignoram a lista.
Como manter um projeto no Python 3.14? Rode uv python pin 3.14 na pasta do projeto. O comando grava um arquivo .python-version que o uv respeita.
Guias relacionados
- Como atualizar o Python no Windows, Mac, Linux e ambientes virtuais
- Gerenciadores de versão do Python
- Como verificar a versão do Python
- Como atualizar pacotes Python
- Polars vs pandas
- Importação circular em Python: erros e correções