Я занимаюсь контейнеризацией своего приложения Python. Обычно я загружаю свой файл .env
и использую dotenv
для чтения переменной.
Пример:
from dotenv import load_dotenv
import os
def test_env():
load_dotenv()
print(f"private_key : {repr(os.environ.get('PRIVATE_KEY'))}")
if __name__ == '__main__':
test_env()
и в моем файле .env
мне нужно было бы заключить переменную в кавычки, чтобы это тоже работало. Пример:
PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n.....=\n-----END PRIVATE KEY-----\n"
Это правильно распечатывается в моем приложении Python.
Однако, когда я запускаю тот же код, но с использованием Docker --env-file
, к каждому \
добавляется дополнительный \n
.
Пример команды докера:
docker run --env-file ./.env -d -p $(RUN_PORT):$(RUN_PORT) --name $(DOCKER_CONTAINER_NAME) $(FULL_IMG_NAME)
Результат выглядит так: '-----BEGIN PRIVATE KEY-----\\n...=\\n-----END PRIVATE KEY-----\\n'
Это независимо от того, содержит ли файл .env
"" вокруг переменной или нет. Все, что "" делает с переменной, - это ее литерал, чего нет в случае с dotenv
.
Что должно быть сделано?
dotenv
больше не используется, так как файла .env
нет. Docker вводит переменные env непосредственно в программу. Когда я печатаю с помощью os.environ.get()
, я получаю дополнительный символ.
Разница в том, что dotenv интерпретирует \n
и заменяет его на символ новой строки. os.environ.get
нет, поэтому он возвращает \n
в виде двух символов. Затем, когда вы его печатаете, repr
убирает обратную косую черту и добавляет дополнительную обратную косую черту.
Хорошо, думаю, теперь я понял. Мне нужно обновить переменную .env
и заменить /n
символом новой строки? Под символом новой строки вы подразумеваете буквально новую строку в моей переменной в файле .env
?
Я попытался поместить символы новой строки в файл среды, но не смог заставить его работать. Я думаю, что лучшее решение — позволить Python обрабатывать escape-символы. Я опубликовал ответ, показывающий, как это сделать.
dotenv
обрабатывает текст и декодирует escape-последовательности. Таким образом, он заменяет \n
символом новой строки.
os.environ.get
нет, поэтому ваша строка содержит два символа: обратную косую черту и 'n'. Затем функция repr
экранирует обратную косую черту при ее печати, поэтому вы получаете двойную обратную косую черту, которую видите.
Вы можете самостоятельно обрабатывать escape-последовательности в Python, используя такую функцию decode
:
import os
def test_env():
private_key = bytes(os.environ.get('PRIVATE_KEY'), "utf-8").decode("unicode_escape")
print(f"private_key : {repr(private_key)}")
if __name__ == '__main__':
test_env()
Это должно прочитать закрытый ключ из переменной среды и изменить \n
на новую строку, как вы привыкли dotenv
делать.
Черт, так мне придется сделать это для каждой переменной среды, чтобы убедиться, что у меня нет экранирующих символов? Попробую, спасибо!
Проблема не столько в добавлении обратной косой черты, сколько в том, что
\n
преобразуется в символ новой строки при использовании dotenv. Файл среды Docker этого не делает, поэтому переменная среды содержит два символа: обратную косую черту и букву «n». И когда ваша программа Python печатает это, она добавляет дополнительную обратную косую черту, чтобы избежать обратной косой черты. Чтобы это исправить, вы можете заменить\n
символом новой строки при чтении переменной среды.