O módulo importlib.metadata lê metadados de distribuições Python instaladas sem precisar importar os pacotes. Ele permite consultar versão, nome, autor, requisitos, arquivos, entry points e o relacionamento entre distribuições e módulos importáveis. É útil em CLIs de diagnóstico, sistemas de plugins, relatórios de suporte, verificações de compatibilidade, inventários e observabilidade.
Uma distribuição instalada não é a mesma coisa que um módulo. O comando pip install beautifulsoup4, por exemplo, instala uma distribuição cujo pacote importável principal tem outro nome. A API trabalha com metadados de instalação, normalmente presentes em diretórios .dist-info ou .egg-info.
Consulte uma versão
A função version() retorna a versão declarada pela distribuição.
from importlib.metadata import version
print(version("requests"))
Use o nome da distribuição, não necessariamente o nome usado no import.
PackageNotFoundError
Quando a distribuição não está instalada, a API lança PackageNotFoundError.
from importlib.metadata import PackageNotFoundError, version
try:
versao = version("meu-plugin")
except PackageNotFoundError:
versao = None
Diferencie pacote ausente de metadados inválidos ou ambiente incorreto.
Não importe apenas para obter a versão
Muitos pacotes expõem __version__, mas importá-los pode ser lento ou produzir side effects.
importlib.metadata.version() lê a informação instalada sem executar o código da biblioteca.
O nome da distribuição
Nomes são comparados segundo regras de normalização do ecossistema de packaging.
Hífens, underscores e diferenças de maiúsculas podem ser normalizados. Preserve o nome canônico exibido nos metadados para relatórios.
metadata
metadata(name) devolve uma estrutura semelhante a headers de e-mail.
from importlib.metadata import metadata
meta = metadata("requests")
print(meta["Name"])
print(meta["Version"])
print(meta.get("Summary"))
Nem todo campo é obrigatório ou preenchido corretamente por todas as distribuições.
Campos repetidos
Alguns metadados, como classifiers e requisitos, podem ocorrer várias vezes.
Use métodos adequados da estrutura retornada para recuperar todos os valores, em vez de presumir uma única string.
Texto longo
Metadados podem incluir descrição extensa. Não registre o objeto inteiro em logs de produção.
Selecione campos necessários e limite tamanho.
requires
requires(name) retorna requisitos declarados pela distribuição.
from importlib.metadata import requires
for requisito in requires("requests") or []:
print(requisito)
As strings seguem a sintaxe de requisitos do packaging, podendo incluir versões, extras e environment markers.
Analise requisitos com packaging
Não divida strings manualmente. Use packaging.requirements.Requirement.
from packaging.requirements import Requirement
req = Requirement('urllib3<3,>=1.21.1')
print(req.name, req.specifier)
Markers precisam ser avaliados no ambiente correto.
Dependência declarada não significa importada
Um requisito pode ser opcional, específico de plataforma ou usado apenas por uma feature.
Para módulos realmente carregados, combine metadados com testes e análise de imports.
files
files(name) lista arquivos registrados na distribuição.
from importlib.metadata import files
for arquivo in files("requests") or []:
print(arquivo)
O resultado pode ser None quando a instalação não possui um registro completo.
PackagePath
Itens retornados oferecem informações e métodos para localizar o arquivo.
for item in files("meu-pacote") or []:
caminho = item.locate()
print(caminho)
Verifique existência e não presuma que todo item ainda está presente em uma instalação modificada.
Hashes e tamanhos
Registros de arquivos podem incluir hash e tamanho, dependendo da distribuição.
Esses valores ajudam em auditorias, mas não substituem uma política completa de verificação de integridade e assinatura.
distribution
distribution(name) retorna um objeto Distribution.
from importlib.metadata import distribution
dist = distribution("requests")
print(dist.version)
print(dist.metadata["Name"])
O objeto centraliza acesso a metadados, arquivos, requisitos e entry points.
locate_file
Um objeto Distribution pode localizar um caminho relativo da instalação.
caminho = dist.locate_file("requests/__init__.py")
Valide o resultado antes de abrir. Instalações editáveis e layouts especiais podem apontar para fora de site-packages.
distributions
distributions() percorre distribuições visíveis no ambiente.
from importlib.metadata import distributions
for dist in distributions():
print(dist.metadata.get("Name"), dist.version)
Ordene o resultado e limite campos para um inventário reproduzível.
Inventário do ambiente
Um relatório útil inclui nome, versão, origem e talvez hash de arquivos críticos.
Não publique automaticamente o inventário completo; ele pode revelar componentes internos e superfície de ataque.
Ambientes virtuais
A API vê distribuições disponíveis ao interpretador atual.
Execute com o mesmo sys.executable da aplicação. Consultar pelo Python global gera um inventário diferente do venv.
Instalações editáveis
Editable installs possuem metadados instalados, mas o código pode apontar para um checkout.
Relatórios devem distinguir artefato imutável de ambiente de desenvolvimento.
packages_distributions
packages_distributions() mapeia nomes importáveis de topo para distribuições.
from importlib.metadata import packages_distributions
mapa = packages_distributions()
print(mapa.get("bs4"))
Um módulo pode ser fornecido por mais de uma distribuição, especialmente em namespaces.
Módulo versus distribuição
Use esse mapeamento ao relacionar resultados de modulefinder no Python com versões instaladas.
Não tente deduzir o nome da distribuição apenas capitalizando o import.
entry_points
Entry points são declarações de extensões, comandos e plugins instalados.
from importlib.metadata import entry_points
plugins = entry_points(group="minhaapp.plugins")
for ep in plugins:
print(ep.name, ep.value)
A forma de seleção evoluiu entre versões; use a API da versão mínima declarada.
Grupos
Um grupo cria um namespace lógico, como console_scripts ou minhaapp.plugins.
Escolha um nome de grupo específico da organização para evitar conflitos.
EntryPoint
Cada entry point possui nome, grupo e valor. O valor normalmente referencia um módulo e objeto.
for ep in plugins:
print(ep.group, ep.name, ep.value)
Você pode inspecionar metadados sem carregar o plugin.
load
EntryPoint.load() importa o módulo e retorna o objeto declarado.
plugin_factory = ep.load()
plugin = plugin_factory()
Essa chamada executa importação e pode produzir side effects ou falhar.
Não carregue todos os plugins automaticamente
Filtre por configuração, compatibilidade, autorização e versão antes de chamar load().
Plugins de terceiros devem ser isolados ou executados com privilégios adequados ao risco.
Duplicatas de entry point
Duas distribuições podem declarar o mesmo nome no mesmo grupo.
Defina uma política explícita: erro, prioridade configurada ou seleção por distribuição. Não dependa da ordem do ambiente.
Versão da API de entry points
APIs anteriores retornavam estruturas diferentes e usavam métodos de seleção distintos.
Centralize a compatibilidade e teste em todas as versões suportadas.
Console scripts
O grupo console_scripts define comandos instalados por ferramentas de packaging.
Inspecionar entry points permite diagnosticar por que uma CLI não foi criada ou qual objeto deveria ser chamado.
Não execute console scripts com load sem política
Um entry point de console foi projetado para ser chamado como comando, com argumentos e código de saída.
Para fidelidade, use o executável instalado ou um subprocesso, em vez de chamar o objeto arbitrariamente.
Metadados de versão e compatibilidade
Compare versões com packaging.version.Version, não como strings.
from packaging.version import Version
if Version(version("meu-plugin")) < Version("2.0"):
raise RuntimeError("plugin antigo")
Strings lexicográficas tratam 10 e 2 incorretamente.
Requisitos e markers
Environment markers podem depender de Python, plataforma, implementação e extras.
Avalie-os com a biblioteca packaging e o ambiente de destino.
Extras
Extras representam conjuntos opcionais de dependências, como pacote[postgres].
Os metadados não garantem que o extra foi instalado como intenção; mostram requisitos e distribuições presentes.
Licenças
Campos de licença e classifiers ajudam em inventários, mas podem estar ausentes, ambíguos ou desatualizados.
Para compliance, use uma ferramenta dedicada e revisão das licenças reais.
URLs do projeto
Metadados podem incluir homepage, repositório, documentação e issue tracker.
Não confie em URLs de uma distribuição desconhecida como destino seguro para automação.
Cache
Consultas repetidas podem ser cacheadas pela aplicação quando o ambiente não muda.
Instalar ou remover distribuições durante o processo torna caches antigos. Em produção, ambientes imutáveis simplificam a política.
Performance
Consultar uma versão é barato em uso comum, mas enumerar todas as distribuições e arquivos pode ser custoso.
Faça inventários no startup ou sob demanda, não em cada request.
Não dependa de ordem
A ordem de distributions(), files e entry points não deve definir comportamento.
Ordene explicitamente e resolva conflitos por política.
Metadados incompletos
Instalações antigas, manuais ou corrompidas podem não possuir todos os registros.
Use fallbacks claros e marque o ambiente como não verificável quando campos críticos faltam.
Pacotes da biblioteca padrão
A maioria dos módulos da standard library não corresponde a distribuições instaladas consultáveis por nome.
Use sysconfig e a versão do Python para identificar a biblioteca padrão.
Distribuições vendorizadas
Uma aplicação pode incluir código de terceiros dentro do próprio pacote sem metadados separados.
importlib.metadata não detecta automaticamente componentes vendorizados como distribuições independentes.
Containers
Gere um inventário durante o build e valide no runtime final.
Multi-stage builds podem instalar pacotes em uma etapa diferente; consulte a imagem que realmente será executada.
SBOM
Os metadados ajudam a construir uma Software Bill of Materials, mas uma SBOM completa precisa considerar bibliotecas nativas, sistema operacional, arquivos vendorizados e hashes.
Use formatos e ferramentas de SBOM apropriados.
Segurança
Listar versões pode ajudar um operador, mas também revela componentes a um atacante.
Proteja endpoints de diagnóstico e não exponha inventários completos publicamente.
Metadados não são confiança
Nome, versão e autor são declarações do pacote instalado.
Verifique origem, assinatura, hash e índice confiável conforme a política de supply chain.
Plugins e isolamento
Entry points facilitam descoberta, mas load() executa código.
Carregue somente plugins aprovados e considere processos separados para extensões de terceiros.
Observabilidade
Inclua versões de componentes principais em logs de startup ou métricas com cardinalidade controlada.
Não adicione todas as distribuições como labels de métricas.
Relatórios de suporte
Um comando de diagnóstico pode produzir ambiente, Python, plataforma e versões selecionadas.
Ofereça opção de redigir paths, nomes internos e dados do sistema antes do compartilhamento.
Integração com pkgutil
pkgutil descobre módulos oferecidos pelo sistema de importação; importlib.metadata descreve distribuições instaladas e plugins declarados.
Veja pkgutil no Python.
Integração com importlib.resources
Depois de identificar uma distribuição ou plugin, recursos devem ser acessados pela âncora do pacote.
Veja importlib.resources no Python.
Testes
Crie distribuições fixture ou instale wheels de teste. Cubra pacote ausente, versão, requisitos, files ausente, entry points duplicados, editable install e namespace packages.
Não dependa das distribuições instaladas na máquina do desenvolvedor.
Compatibilidade
O módulo entrou na biblioteca padrão em versões modernas e continuou evoluindo. Para versões antigas, existe o backport importlib_metadata.
Centralize imports e diferenças de API em uma camada do projeto.
Erros comuns
Os erros mais frequentes são usar nome de import em vez da distribuição, importar para obter versão, comparar versões como strings, chamar load() em todo plugin, depender da ordem de entry points, presumir metadados completos, enumerar tudo por request e expor inventários publicamente.
Conclusão
importlib.metadata consulta versões, requisitos, arquivos, distribuições e entry points sem importar o código correspondente. Use version() para verificações simples, distribution() para detalhes e entry_points() para plugins declarados.
Trate metadados como informação, não confiança, resolva nomes de módulo e distribuição corretamente e carregue plugins apenas depois de validar. Consulte a documentação oficial de importlib.metadata e o artigo de modulefinder no Python.







