2026, Jan 11 06:03
URL из .env в Python печатаются с \x3a: как добиться стабильности
Разбираем, почему URL из .env в Python выглядят как http\x3a//..., откуда берётся кодирование и как исправить проблему через python-dotenv с override=True.
Шестнадцатеричные последовательности в URL, попадающем из .env, способны сломать иначе простой процесс настройки. Особенно странно выглядит ситуация, когда одно и то же значение из .env то выводится как нормальный URL, то внезапно с подстановкой \x3a вместо двоеточий. Ниже — краткое объяснение, что происходит, и как добиваться стабильной загрузки переменных окружения в Python.
Воспроизводим странный URL из .env
Начните с простого значения в окружении:
GATEWAY_URL="http://localhost:9000"
Загрузим его в Python через python-dotenv и прочитаем через os.getenv. Даже дополнительный проход через unquote здесь не помогает:
import os
from urllib.parse import unquote
from dotenv import load_dotenv
load_dotenv()
service_host = os.getenv("GATEWAY_URL", "")
print(service_host)
service_host = unquote(os.getenv("GATEWAY_URL", ""))
print(service_host)
Оба вывода могут выглядеть так: http\x3a//localhost\x3a9000.
Теперь добавьте ещё одну запись:
NEXT_GATEWAY="http://localhost:9001"
Если прочитать её сразу после редактирования файла, можно получить привычный результат:
load_dotenv()
alt_host = os.getenv("NEXT_GATEWAY", "")
print(alt_host)
Вывод может быть таким: http://localhost:9001. Однако после перезапуска виртуального окружения всё «откатывается», и строка печатается как http\x3a//localhost\x3a9001. Речь не про «очистку» URL; важна именно несогласованность между тем, что записано в .env, и тем, что приходит в Python.
Что на самом деле происходит
Поведение непоследовательно, потому что значение, попадающее в Python, иногда оказывается заранее закодированным ещё до того, как python-dotenv прочитает ваш .env. Иными словами, в окружении уже может лежать изменённая версия переменной, и простой вызов os.getenv возвращает именно её. Замена кавычек или ручная «очистка» строки не отвечает на вопрос, почему некорректное содержимое вообще оказывается в окружении.
Правка, которая возвращает стабильность
На практике проблему решает принудительная перезапись существующих переменных окружения в python-dotenv. Это гарантирует, что значения из .env заменят всё, что могло быть подмешано ранее:
from dotenv import load_dotenv
import os
load_dotenv(override=True)
cloud_addr = os.getenv("SUPABASE_URL")
print(cloud_addr)
С установленным флагом override ранее искажённый URL вроде
https\3a//xxxxxxxxxxxxxxxxxx.supabase.co
печатается как
https://xxxxxxxxxxxxxxxxxx.supabase.co
Также было отмечено, что это поведение связано с недавно исправленной проблемой в VSCode; принудительный override возвращает работоспособность даже на затронутой конфигурации. Подробности: https://github.com/microsoft/vscode/issues/248468.
Почему это важно
Конфигурация через переменные окружения должна быть предсказуемой между платформами и сессиями. Если рантайм подхватывает уже изменённую переменную, сегодня вы видите рабочий URL, а после перезапуска — его шестнадцатерично закодированный вариант. Это ломает ожидания в CI/CD, локальной разработке и любой истории про воспроизводимые среды. Гарантируйте, что побеждает значение, загруженное из .env, — так вы избегаете тонких и затратных по времени отладок.
Итоги
Если URL из .env время от времени появляются с \x3a или \3a вместо двоеточий, загружайте окружение с включённой перезаписью. Это устраняет несогласованность из‑за предварительно заполненных значений или инъекций со стороны редактора и возвращает чистый, предсказуемый процесс конфигурации. Если вы используете VSCode, имейте в виду связанный баг; описанный обходной путь работает даже там, где он проявляется. Ставьте во главу угла авторитетность .env и проверяйте фактические значения при старте, чтобы сразу ловить любые расхождения.