Короткий ответ
Хранение секретов в коде означает, что они попадают в систему контроля версий и видны всем, у кого есть доступ к репозиторию, тогда как переменные окружения задаются отдельно от кода на каждом окружении и не коммитятся вместе с исходниками.
Как это работает подробнее
Приложение читает значения через os.environ или библиотеки вроде python-dotenv/pydantic-settings при старте, а сами значения задаются в конфигурации деплоя, секрет-хранилище или .env-файле, явно исключённом из git через .gitignore.
Пример кода
example.py
import os
DATABASE_URL = os.environ.get("DATABASE_URL")
if not DATABASE_URL:
raise RuntimeError("DATABASE_URL is not set")
# .gitignore
# .envЧто использовать на практике
- Практика. Это позволяет использовать разные значения на dev/staging/production без изменения кода и ротировать секрет, не делая новый релиз; для продакшена одних .env файлов часто недостаточно — используют менеджеры секретов (Vault, AWS Secrets Manager) с контролем доступа и аудитом.
Подводные камни
- Риск. Коммитят .env файл с реальными значениями «по ошибке»; хардкодят секрет «временно для теста» и забывают убрать перед мерджем; логируют значения переменных окружения целиком при отладке конфигурации.