runpy no Python: execute módulos e scripts

Publicado em: 27/08/2026
Tempo de leitura: 8 minutos
Close-up view of a computer screen displaying code in a software development environment.

O módulo runpy executa código Python localizado pelo sistema de importação ou por um caminho de arquivo, retornando o namespace global resultante. Ele implementa parte da lógica usada por comandos como python -m pacote.modulo e é útil em launchers, test harnesses, ferramentas educacionais, wrappers de CLI e sistemas que precisam executar um módulo como se fosse o programa principal.

O módulo não cria isolamento. O código é executado no processo atual, pode alterar estado global, importar dependências, abrir arquivos, iniciar threads e encerrar o programa. Use-o apenas com código confiável e entenda como ele manipula variáveis especiais como __name__, __spec__, __package__ e sys.argv.

run_module

runpy.run_module(mod_name, ...) localiza um módulo pelo sistema de importação e executa seu código.

import runpy

namespace = runpy.run_module("meu_pacote.modulo")
print(namespace.keys())

O nome deve ser importável no ambiente atual.

O retorno é um dicionário

Depois da execução, o retorno contém os globals definidos pelo módulo.

resultado = runpy.run_module("configuracao")
valor = resultado.get("CONFIG")

Objetos retornados continuam vivos e podem referenciar módulos, arquivos, locks ou outros recursos.

run_name

O parâmetro run_name controla o valor de __name__ durante a execução.

runpy.run_module(
    "meu_pacote.cli",
    run_name="__main__",
)

Isso ativa blocos condicionais como if __name__ == "__main__":.

Executar como __main__

Executar um módulo com run_name="__main__" aproxima o comportamento de python -m, mas detalhes de sys.argv e sys.modules dependem de outras opções.

Para uma CLI pública, normalmente é mais simples invocar o interpretador com -m em um subprocesso.

Pacotes e __main__.py

Quando o nome identifica um pacote, o mecanismo pode localizar e executar o submódulo pacote.__main__.

meu_pacote/
    __init__.py
    __main__.py

Esse é o padrão para pacotes executáveis com python -m meu_pacote.

alter_sys

Com alter_sys=True, runpy altera temporariamente alguns elementos de sys, como sys.argv[0] e uma entrada em sys.modules.

runpy.run_module(
    "meu_pacote.cli",
    run_name="__main__",
    alter_sys=True,
)

As alterações são restauradas ao final, inclusive quando ocorre exceção.

alter_sys não é thread-safe

Outras threads podem observar o estado temporário e receber um módulo parcialmente inicializado ou um valor de argv inesperado.

Não use alter_sys=True enquanto threads concorrentes dependem desses globals. Prefira um processo separado.

init_globals

init_globals fornece valores iniciais para o namespace.

namespace = runpy.run_module(
    "relatorio",
    init_globals={"AMBIENTE": "teste"},
)

O módulo pode sobrescrever essas chaves durante a execução.

Não use init_globals como segurança

Fornecer um dicionário reduzido não impede o código de importar builtins, acessar filesystem ou introspectar objetos.

Ele é um mecanismo de configuração e teste, não sandbox.

Variáveis especiais

runpy define valores apropriados para variáveis como __name__, __file__, __cached__, __loader__, __package__ e __spec__.

Esses valores permitem que imports relativos e diagnósticos funcionem de forma semelhante ao sistema normal de importação.

__spec__

__spec__ descreve como o módulo foi localizado e carregado. Em pacotes executáveis, o nome real do spec continua relacionado ao módulo encontrado, mesmo quando __name__ é alterado.

Ferramentas devem usar __spec__.name para identidade importável e __name__ para o contexto de execução.

run_path

runpy.run_path(path_name, ...) executa código a partir de um caminho.

namespace = runpy.run_path("scripts/tarefa.py")

O caminho pode apontar para um arquivo Python ou para uma entrada válida de sys.path que contenha __main__.py.

Diretórios executáveis

Se path_name é um diretório, runpy adiciona temporariamente a entrada e procura um __main__.py.

Confirme que o diretório contém o entry point esperado. Caso contrário, outro __main__ visível no path pode causar comportamento surpreendente em alguns cenários.

Arquivos ZIP

Um ZIP válido no sistema de importação pode conter __main__.py e ser executado por run_path().

Isso é a base de aplicações .pyz. Veja zipapp no Python.

run_path e run_name

O padrão de run_name em run_path() é um valor especial. Defina __main__ quando quiser ativar o comportamento de programa principal.

runpy.run_path(
    "scripts/tarefa.py",
    run_name="__main__",
)

Diferença para importlib.import_module

importlib.import_module() importa e registra um módulo de forma normal em sys.modules. Imports repetidos normalmente reutilizam a mesma instância.

run_module() executa o código em um namespace novo e é voltado ao comportamento de script, não ao carregamento convencional de uma biblioteca.

Execuções repetidas

Chamar runpy duas vezes pode executar efeitos de nível de módulo duas vezes.

Isso inclui registros duplicados, criação de threads, handlers, escrita em arquivos e conexões. O código executado deve ser projetado para esse lifecycle ou rodar em processo descartável.

sys.modules

Dependendo de alter_sys, o módulo executado pode não permanecer registrado como uma importação normal.

Imports feitos pelo código permanecem em sys.modules e alteram o processo.

Estado global

O namespace retornado não captura todas as mudanças. O código pode alterar variáveis de outros módulos, logging, locale, diretório atual, sinais e caches.

Não espere desfazer uma execução simplesmente descartando o dicionário.

Exceções

Exceções lançadas pelo código são propagadas para o caller.

try:
    runpy.run_module("meu_pacote.cli", run_name="__main__")
except SystemExit as erro:
    print("código de saída", erro.code)

CLIs frequentemente chamam sys.exit(), que gera SystemExit.

KeyboardInterrupt

Uma interrupção pode atravessar a execução. Defina se o launcher deve encerrar, cancelar apenas a tarefa ou traduzir o estado.

Não capture BaseException sem uma política clara.

Argumentos de linha de comando

runpy não é uma API completa de subprocesso. Para simular argumentos, alterações em sys.argv afetam o processo inteiro.

Prefira chamar uma função main(argv) diretamente ou usar subprocesso.

Arquitetura de CLI recomendada

def main(argv=None):
    args = parser.parse_args(argv)
    return executar(args)

if __name__ == "__main__":
    raise SystemExit(main())

Essa estrutura permite testes sem runpy e mantém o entry point fino.

Testes

runpy é útil para verificar que um módulo funciona como -m.

resultado = runpy.run_module(
    "meu_pacote",
    run_name="__main__",
)

Porém, se a CLI altera sys, abre processos ou chama exit, um subprocesso oferece isolamento mais fiel.

Use subprocess para fidelidade

subprocess.run(
    [sys.executable, "-m", "meu_pacote"],
    check=True,
)

Isso separa argv, módulos, sinais, ambiente e código de saída.

Performance

Execuções repetidas recompilam ou reutilizam caches conforme o sistema de importação, mas o corpo é executado novamente.

Não use runpy como mecanismo de chamada frequente entre componentes. Importe uma função e chame-a.

Plugins

Runpy não é o mecanismo ideal para plugins. Plugins devem expor APIs, entry points ou funções claras.

Executar um plugin inteiro como script dificulta contratos, cleanup e tratamento de erros.

Ferramentas educacionais

Um ambiente de aprendizagem pode usar runpy para executar exemplos em processo separado.

O isolamento deve limitar filesystem, rede, CPU, memória e tempo. Código de aluno não deve rodar no processo da aplicação.

Launchers internos

Um launcher pode selecionar módulos confiáveis a partir de uma allowlist e executá-los.

Não aceite diretamente um nome de módulo fornecido por usuário; isso pode permitir executar qualquer código importável no ambiente.

Validação de nomes

Mapeie comandos públicos a nomes internos fixos.

COMANDOS = {
    "relatorio": "minhaapp.comandos.relatorio",
    "limpeza": "minhaapp.comandos.limpeza",
}

Autorização deve ser aplicada antes da seleção.

Código não confiável

runpy executa Python com os privilégios do processo. Não é seguro para arquivos enviados, snippets ou pacotes de origem desconhecida.

Use processo ou container isolado com políticas de recursos.

Paths não confiáveis

run_path() pode executar qualquer script acessível. Resolva paths dentro de uma raiz permitida e recuse symlinks ou escapes.

Não execute diretamente arquivos temporários compartilhados.

Diretório atual

O código pode depender do current working directory. runpy não cria automaticamente um contexto isolado de paths relativos.

Prefira paths absolutos e APIs de recursos de pacote.

Logging

O módulo executado pode configurar handlers globais e duplicá-los em execuções repetidas.

Bibliotecas devem evitar basicConfig() automático; a aplicação deve possuir a configuração.

Threads e tarefas

Threads iniciadas pelo código podem continuar depois do retorno.

Um subprocesso descartável fornece cleanup mais previsível.

Integração com faulthandler

Para módulos confiáveis que podem travar, ative faulthandler e imponha deadline em processo separado.

Um dump antes do encerramento ajuda a identificar a linha bloqueada.

Empacotadores

Ferramentas congeladas podem implementar -m e runpy de maneiras específicas. Módulos e recursos precisam estar incluídos no artefato.

Teste no executável final, não apenas no ambiente de desenvolvimento.

__cached__ e bytecode

O namespace pode incluir o caminho de cache associado ao módulo.

Não use esse valor como garantia de que o arquivo existe ou pode ser distribuído. Caches dependem da versão do Python.

Observabilidade

Registre nome lógico, versão da aplicação, duração, resultado e código de saída traduzido. Evite registrar todo o namespace retornado.

O dicionário pode conter segredos e objetos com representações caras.

Testes de concorrência

Se uma aplicação usar runpy enquanto outras threads estão ativas, teste alterações em sys, imports e handlers.

A recomendação geral para execução independente continua sendo subprocesso.

Erros comuns

Os erros mais frequentes são confundir runpy com import normal, usar alter_sys=True em programa multithread, compartilhar estado entre execuções, simular argv globalmente, aceitar nomes ou paths arbitrários, esperar cleanup completo e usar runpy como sandbox.

Conclusão

runpy executa módulos e scripts usando a infraestrutura do Python e retorna o namespace resultante. Use run_module() para nomes importáveis, run_path() para caminhos e run_name="__main__" quando quiser comportamento de entry point.

Para isolamento, argumentos e códigos de saída reais, prefira subprocessos. Consulte a documentação oficial de runpy e o artigo de pkgutil no Python para descobrir módulos antes de selecioná-los.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pkgutil no Python: descubra pacotes

    Aprenda pkgutil no Python para listar módulos, percorrer pacotes, descobrir plugins, consultar importers e ler recursos com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    modulefinder no Python: descubra imports

    Aprenda modulefinder no Python para descobrir imports, dependências transitivas, módulos ausentes, paths, plugins e limitações da análise estática.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    Vivid close-up of code on a computer screen showcasing programming details.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    py_compile no Python: compile um arquivo

    Aprenda py_compile no Python para compilar um arquivo, controlar .pyc, dfile, otimização, invalidação por hash e erros de build.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compileall no Python: gere bytecode .pyc

    Aprenda compileall no Python para gerar .pyc, validar sintaxe, compilar em paralelo, controlar otimização, paths e builds reproduzíveis.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    A classic MS-DOS terminal screen displayed on a laptop keyboard with vivid illumination.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    codeop no Python: compile comandos interativos

    Aprenda codeop no Python para detectar comandos completos, incompletos ou inválidos, criar REPLs e preservar flags de __future__ com segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    linecache no Python: leia linhas do código

    Aprenda linecache no Python para recuperar linhas de código, atualizar cache, integrar tracebacks, lidar com loaders e proteger caminhos.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026