Arquivo .env em Executáveis Python
Entendendo o Conceito
Em desenvolvimento, com o script .py rodando direto pelo editor, a função load_dotenv() encontra o arquivo .env sem problemas, pois procura com base no diretório do arquivo Python original.
O problema aparece ao compilar o script em executável com a opção --onefile do PyInstaller. Nesse modo, o PyInstaller descompacta o código em uma pasta temporária oculta do sistema operacional (geralmente chamada de _MEIPASS). O programa compilado procura o .env dentro dessa pasta temporária, em vez da pasta onde o executável está rodando, e falha ao carregar as configurações.
A solução é calcular o caminho do .env explicitamente: em ambiente compilado, usa-se o diretório do próprio executável; em desenvolvimento, usa-se o diretório do script.
Passo a Passo
- Substitua a chamada simples de
load_dotenv()pela função abaixo, que detecta o ambiente antes de carregar o arquivo:
import os
import sys
from dotenv import load_dotenv
def carregar_configuracoes():
# Detecta se o script está rodando como um executável compilado (frozen)
if getattr(sys, 'frozen', False):
# Caminho da pasta onde o executável (.exe) está localizado fisicamente
diretorio_executavel = os.path.dirname(sys.executable)
else:
# Caminho em modo de desenvolvimento (rodando o script .py direto no editor)
diretorio_executavel = os.path.dirname(os.path.abspath(__file__))
# Define o caminho absoluto para o arquivo .env ao lado do executável
caminho_env = os.path.join(diretorio_executavel, '.env')
# Carrega o arquivo .env específico usando o caminho calculado
load_dotenv(dotenv_path=caminho_env)
# Executa a função para garantir que as variáveis sejam carregadas antes de todo o resto
carregar_configuracoes()
# Agora você pode ler normalmente suas variáveis de ambiente
api_key = os.getenv("API_KEY")
print(f"Chave carregada com sucesso: {api_key}")
- Compile o executável com o PyInstaller. O arquivo
.envnão deve ser embutido no executável, pois geralmente contém dados confidenciais ou valores que o usuário final pode querer alterar; ele deve ficar externo, editável:
pyinstaller --onefile seu_script.py
Localize o executável gerado na pasta
distcriada pelo PyInstaller.Monte a pasta de entrega com o executável e o arquivo
.envlado a lado:
MinhaFerramenta/
├── seu_script.exe
└── .env
- Para alterar uma configuração, o usuário abre o
.envem um editor de texto, salva e executa o programa novamente.
Explicando o código
getattr(sys, 'frozen', False): verifica se o código está rodando como executável compilado.frozené uma propriedade que o PyInstaller adiciona aosyspara indicar que o programa não é mais um script comum.sys.executable: retorna o caminho completo de onde o executável está rodando no computador do usuário.os.path.abspath(__file__): em desenvolvimento, retorna o caminho absoluto do arquivo.pyem execução.os.path.dirname(...): remove o nome do arquivo do caminho e retorna apenas o diretório onde ele está salvo.os.path.join(diretorio_executavel, '.env'): junta diretório e nome de arquivo de forma compatível com Windows (barra invertida\) e Linux/macOS (barra/).load_dotenv(dotenv_path=caminho_env): carrega o.enva partir do caminho calculado, em vez de procurar no diretório padrão.- A chamada
carregar_configuracoes()antes do resto do código garante que as variáveis estejam disponíveis para todo o programa.
Observações
- Não usar
os.getcwd()para localizar o.env: essa função retorna o diretório de onde o terminal foi aberto, não onde o executável está salvo. Se o programa for iniciado a partir de outro diretório, o.envnão será encontrado. - Nunca enviar o
.envreal para um repositório público. Criar um arquivo.gitignorecontendo.env, e um arquivo.env.example(sem senhas reais) para servir de modelo. - Se o executável for movido sem o
.envao lado, o programa não terá de onde ler as configurações. Distribuir sempre o programa em uma pasta compactada (.zip) contendo executável e.envmodelo. - Ao distribuir, o
.envnão deve ser embutido no executável, senão ninguém conseguirá editá-lo externamente.
Referências
- Documentação oficial do python-dotenv: https://github.com/theskumar/python-dotenv
- Documentação oficial do PyInstaller: https://pyinstaller.org/