Configure Python environment variables

2 min read07 November 2026

Environment variables separate configuration from code: the same program runs locally, in test and in production with different values, with no edits and no secrets in the repository. On app hosting, they are defined in the panel and injected when the process starts.

Read a variable

Python
import os

token = os.environ["DISCORD_TOKEN"]
port = int(os.environ.get("PORT", "8000"))
debug = os.environ.get("DEBUG", "false").lower() == "true"

os.environ["X"] raises KeyError when the variable is missing: that is often desirable for a required secret, provided you print a clear message. os.environ.get("X", "default") supplies a fallback. Convert integers and booleans explicitly; the string "false" is truthy in Python if you test it directly.

Never use a secret as a default value in code. A hard-coded token ends up in Git, an archive or a screenshot.

Panel and local .env file

In the panel, variables belong to the service and apply on restart. Changing a value does not affect the running process.

Locally, use an unversioned .env file:

Text
DISCORD_TOKEN=your-local-token
DATABASE_URL=postgresql://user:password@localhost:5432/database
DEBUG=true

With python-dotenv, load it only in development:

Python
from dotenv import load_dotenv
load_dotenv()

By default, load_dotenv does not override an existing variable: in production, panel values keep priority. Do not commit .env; version a .env.example with names and empty values.

Secret rotation

A secret must be changeable without redeploying code. For a Discord token, create a new one in the portal, update the variable, restart, verify the connection, then revoke the old one. For a database, create a replacement user or password, test it, then remove the old access.

If a secret leaked into Git, removing it from the last commit is not enough: it remains in history and in clones. Treat it as compromised and revoke it.

Least privilege and logging

  • One secret per service, not a token shared across applications.
  • Minimal rights for the database user.
  • No sensitive variable in logs or HTTP responses.
  • Panel access protected by a strong password and two-factor authentication when available.

Check

After a change, restart and confirm in the log that configuration loaded without printing values. Test the feature that depends on the secret (bot connection, database query). Temporarily remove a variable in a test environment to confirm the failure is explicit rather than silent.

Advertisement

Was this article helpful?

Read next