Pular para o conteúdo
Programação

Como usar arquivo .env no Python para proteger chaves de API

Sim. Usar um arquivo .env é uma forma prática de tirar chaves de API, senhas de banco e outras configurações do código Python. O caminho mais simples é guardar esses valores no ambiente de desenvolvimento, carregar o arquivo com a biblioteca python-dotenv e acessar tudo com os.getenv() ou os.environ.

Mas há uma diferença importante: o .env não criptografa nada. Ele apenas organiza variáveis em um arquivo separado. A proteção vem de não versionar esse arquivo, limitar quem consegue lê-lo e usar o sistema de segredos do serviço onde o programa será executado. A própria documentação do Python trata os.environ como o mapeamento das variáveis disponíveis para o processo; o arquivo é apenas uma maneira conveniente de preenchê-lo durante o desenvolvimento.

Editor de texto com código Python e uma visualização gerada pelo matplotlib
Um editor com código Python ajuda a visualizar onde a configuração entra no programa. (Imagem: MikeRun/Wikimedia Commons, CC BY-SA 4.0)

O que é um arquivo .env no Python?

O .env é um arquivo de texto com pares no formato NOME=VALOR. Um projeto pode usá-lo para armazenar configurações que mudam entre computador, homologação e produção, como a URL de uma API, o nome de um banco ou o modo de execução.

Em vez de escrever uma chave diretamente no programa, você deixa o código esperando por uma variável:

import os

api_key = os.getenv("OPENAI_API_KEY")

O Python não lê automaticamente um arquivo .env. Se a variável ainda não estiver no ambiente do processo, os.getenv() retorna None. É aí que entra o python-dotenv, pacote que lê pares do arquivo e os coloca em os.environ. Por padrão, load_dotenv() procura o arquivo no diretório do projeto ou em diretórios acima e não substitui uma variável que já foi definida no ambiente.

Como configurar o .env passo a passo

1. Instale a biblioteca

Com o ambiente virtual do projeto ativado, instale o pacote:

python -m pip install python-dotenv

Se você ainda não separou as dependências do projeto, vale seguir o caminho mostrado neste guia sobre como criar um ambiente virtual Python no VS Code. O importante é instalar o pacote no mesmo ambiente que executará o programa.

2. Crie o arquivo .env

Na pasta principal do projeto, crie um arquivo chamado exatamente .env:

OPENAI_API_KEY=coloque_sua_chave_aqui
DATABASE_URL=postgresql://USUARIO:VALOR_FICTICIO@localhost:5432/app
APP_ENV=development
PORT=8000

Use valores de exemplo enquanto monta o código. Não cole uma chave real em um tutorial, print ou repositório. Em geral, uma variável por linha resolve o caso mais comum. O formato aceita valores entre aspas quando você precisa preservar espaços ou caracteres especiais, mas a regra mais segura é não complicar o arquivo sem necessidade.

3. Impeça o Git de acompanhar o arquivo

Adicione o .env ao .gitignore antes de fazer o primeiro commit:

.env
.env.*
!.env.example
__pycache__/

Depois, crie um arquivo público chamado .env.example apenas com os nomes das variáveis e valores claramente fictícios:

OPENAI_API_KEY=
DATABASE_URL=postgresql://USUARIO:VALOR_FICTICIO@localhost:5432/nome_do_banco
APP_ENV=development
PORT=8000

Assim, outra pessoa entende o que precisa configurar sem receber seus segredos. Se o arquivo já foi commitado, colocá-lo no .gitignore não apaga o histórico: remova o arquivo do índice e, principalmente, revogue e gere outra chave.

4. Carregue as variáveis no programa

Um exemplo pequeno e seguro para começar é este:

import os
from dotenv import load_dotenv

load_dotenv()

api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
    raise RuntimeError("Defina OPENAI_API_KEY antes de executar o programa")

app_env = os.getenv("APP_ENV", "development")
port = int(os.getenv("PORT", "8000"))

print(f"Ambiente: {app_env}")
print(f"Porta configurada: {port}")
print("Chave de API carregada: sim")

O teste confirma a presença da chave sem exibir seu conteúdo no terminal. Isso parece um detalhe, mas logs de CI, histórico do shell e capturas de tela são lugares comuns para um segredo escapar.

Quando usar os.getenv() ou os.environ?

Os dois acessam variáveis de ambiente, mas servem a estilos diferentes:

  • os.getenv("NOME") retorna None quando a variável não existe e permite um valor padrão, como os.getenv("PORT", "8000");
  • os.environ["NOME"] exige a variável e lança KeyError se ela estiver ausente;
  • os.environ.get("NOME") funciona de modo parecido com getenv().

Para configurações obrigatórias, prefiro falhar cedo com uma mensagem clara. Para opções com valor padrão, getenv() deixa o programa mais flexível. Em ambos os casos, lembre-se de que o valor chega como texto: PORT precisa virar inteiro com int(), e valores como DEBUG=false não se transformam magicamente em um booleano Python.

O .env substitui variáveis definidas no servidor?

Por padrão, não. A chamada load_dotenv() preserva uma variável que já existe no ambiente do processo. Isso permite usar um valor local no .env, mas deixar o servidor, o contêiner ou o serviço de hospedagem fornecer o valor real.

Para testar a precedência, execute:

OPENAI_API_KEY=chave_fornecida_pelo_shell python app.py

O valor definido no shell deve vencer o valor do arquivo. Existe a opção load_dotenv(override=True), mas ela deve ser usada com cuidado: em produção, sobrescrever um segredo injetado pelo ambiente pode trocar uma configuração correta por outra esquecida no arquivo.

Como usar .env em produção sem criar uma falsa sensação de segurança

Em um computador pessoal, o arquivo é conveniente. Em produção, a prática mais segura é cadastrar os valores nas variáveis de ambiente do provedor, no sistema de secrets do CI/CD, no gerenciador de segredos da nuvem ou em uma ferramenta equivalente. O programa continua lendo os.environ; só muda a forma como o valor chega ao processo.

Também adote estas regras:

  • não coloque chaves reais no código, no .env.example, em issues ou em mensagens de log;
  • use permissões restritas para o arquivo local e para a conta que executa o serviço;
  • separe chaves de desenvolvimento, teste e produção;
  • rote uma chave imediatamente se ela aparecer em um repositório ou print;
  • ative secret scanning e push protection quando o provedor oferecer esses recursos.

O GitHub explica que o secret scanning procura credenciais expostas e que o push protection pode bloquear o envio de um segredo antes que ele chegue ao repositório. Isso ajuda, mas não é licença para commitar a chave: detectores podem não reconhecer todo tipo de credencial e uma cópia pode já ter sido clonada.

Erros comuns ao carregar o arquivo

O programa diz que a variável não existe

Confira o nome letra por letra e confirme que o .env está no diretório esperado. Como load_dotenv() procura a partir do local de execução e da estrutura do projeto, executar o script de outra pasta pode causar confusão. Para um caminho explícito, use:

from dotenv import load_dotenv

load_dotenv("config/.env")

A chave aparece como None

Veja se você instalou python-dotenv no ambiente virtual correto, se chamou load_dotenv() antes de ler a variável e se o nome no arquivo é exatamente o mesmo usado no código. Um comando temporário como print(os.getenv("APP_ENV")) pode ajudar a diagnosticar uma configuração sem revelar segredo.

O Git continua mostrando o .env

O arquivo pode já estar sendo rastreado. Confira com git status. Se não houver motivo para mantê-lo no histórico, rode git rm --cached .env, faça um novo commit e revogue os segredos que já foram expostos. Para um vazamento antigo, pode ser necessário limpar o histórico, mas isso não substitui a rotação da credencial.

Conclusão: vale a pena usar .env no Python?

Vale, especialmente em projetos locais, scripts que consomem APIs e aplicações que precisam mudar de configuração entre ambientes. O ganho principal é separar código e configuração e evitar que uma chave fique espalhada por vários arquivos.

O limite precisa ficar claro: .env não é cofre, não cifra valores e não corrige uma chave já vazada. Use-o junto com .gitignore no desenvolvimento e prefira variáveis injetadas por um gerenciador de segredos em produção. Com esse cuidado, o recurso resolve um problema simples sem vender a ilusão de segurança absoluta.

Perguntas frequentes

Arquivo .env é seguro por si só?

Não. Ele é texto puro. A segurança depende de impedir acesso indevido, não versionar o arquivo e trocar a credencial se houver exposição.

Preciso instalar python-dotenv em todo projeto?

Não. Se o sistema, contêiner ou serviço já fornece as variáveis de ambiente, o Python consegue lê-las com a biblioteca padrão os. O pacote é útil para carregar um arquivo local durante o desenvolvimento.

Por que os.getenv() retorna None?

Normalmente porque a variável não foi definida, o nome está diferente, o .env não foi encontrado ou load_dotenv() foi chamado depois da leitura.

Posso enviar o .env para o GitHub se o repositório for privado?

O mais seguro é não enviar. Repositórios privados ainda podem ter colaboradores, cópias, logs e permissões que mudam. Use .env.example sem valores reais e guarde os segredos fora do código.