환경 파일에서 환경 변수 읽기
일반적으로 도커 컨테이너에서 실행되는 파이썬 스크립트를 로컬 환경에서 실행하고 싶습니다.docker-compose.yml
다음과 같이 보이는 env_file을 지정합니다.
DB_ADDR=rethinkdb
DB_PORT=28015
DB_NAME=ipercron
이를 로컬로 실행하기 위해 이 라인을 다음으로 변환하고 싶습니다.
os.environ['DB_ADDR'] = 'rethinkdb'
os.environ['DB_PORT'] = '28015'
os.environ['DB_NAME'] = 'ipercron'
파서를 작성할 수는 있지만 구성 파일에서 환경 변수를 읽을 수 있는 기존 모듈/도구가 있는지 궁금합니다.
저는 파이썬 도트엔브 라이브러리를 사용합니다.라이브러리를 설치하기만 하면 됩니다.pip install python-dotenv
을 생성합니다..env
환경 변수로 파일을 작성하고 다음과 같이 코드의 환경 변수를 가져옵니다.
import os
from dotenv import load_dotenv
load_dotenv()
MY_ENV_VAR = os.getenv('MY_ENV_VAR')
.env
파일 이름:
MY_ENV_VAR="This is my env var content."
이것은 도커 시스템 외부에서 코드를 테스트하고 다시 도커로 되돌리기 위해 준비해야 할 때 하는 방법입니다.
시스템/환경/워크플로우에서 셸 스크립트 사용을 지원하는 경우 다음 두 가지 작업을 수행하는 스크립트를 생성할 수 있습니다.
- .env 파일을 원본으로 저장하고 환경 변수로 내보내기
-
set -a
여기서 "생성되거나 수정된 각 변수 또는 함수에 내보내기 속성이 지정되고 후속 명령의 환경으로 내보내기 위해 표시됩니다."
-
- 파이썬이 스크립트
os.environ.get
샘플 .env 파일(config.env):
TYPE=prod
PORT=5000
샘플 파이썬 코드(test.py ):
import os
print(os.environ.get('TYPE'))
print(os.environ.get('PORT'))
샘플 bash 스크립트(run.sh ):
#!/usr/bin/env bash
set -a
source config.env
set +a
python3 test.py
샘플 런:
$ tree
.
├── config.env
├── run.sh
└── test.py
$ echo $TYPE
$ echo $PORT
$ python3 test.py
None
None
$ ./run.sh
prod
5000
Python 스크립트를 직접 실행하는 경우 (python3 test.py
) 이없source
. 파일, - .env 파일, environ.get
가 반환합니다.None
.
그러나 먼저 .env 파일을 환경 변수에 로드한 다음 Python 스크립트를 실행하는 셸 스크립트로 래핑하면 Python 스크립트가 환경 변수를 올바르게 읽을 수 있습니다.또한 내보낸 환경이 Python 앱/스크립트 실행의 일부로만 존재하도록 합니다.
다른 인기 답변과 비교하면 외부 파이썬 라이브러리가 필요하지 않습니다.
이는 다음과 같은 경우에도 효과적일 수 있습니다.
env_vars = [] # or dict {}
with open(env_file) as f:
for line in f:
if line.startswith('#') or not line.strip():
continue
# if 'export' not in line:
# continue
# Remove leading `export `, if you have those
# then, split name / value pair
# key, value = line.replace('export ', '', 1).strip().split('=', 1)
key, value = line.strip().split('=', 1)
# os.environ[key] = value # Load to local environ
# env_vars[key] = value # Save to a dict, initialized env_vars = {}
env_vars.append({'name': key, 'value': value}) # Save to a list
print(env_vars)
코멘트에서, 당신은 몇 가지 다른 방법들을 찾을 수 있을 것이고 또한 선두를 없애는 몇 가지 구문 분석 옵션도 찾을 수 있을 것입니다.export
키워드또 다른 방법은 python-dotenv 라이브러리를 사용하는 것입니다.건배.
업데이트: 문자열 등에서 변환을 처리하기 위해 나만의 envvar_utils.py를 설정했습니다.
"""Utility functions for dealing with env variables and reading variables from env file"""
import os
import logging
import json
BOOLEAN_TYPE = 'boolean'
INT_TYPE = 'int'
FLOAT_TYPE = 'float'
STRING_TYPE = 'str'
LIST_TYPE = 'list'
DICT_TYPE = 'dict'
def get_envvars(env_file='.env', set_environ=True, ignore_not_found_error=False, exclude_override=()):
"""
Set env vars from a file
:param env_file:
:param set_environ:
:param ignore_not_found_error: ignore not found error
:param exclude_override: if parameter found in this list, don't overwrite environment
:return: list of tuples, env vars
"""
env_vars = []
try:
with open(env_file) as f:
for line in f:
line = line.replace('\n', '')
if not line or line.startswith('#'):
continue
# Remove leading `export `
if line.lower().startswith('export '):
key, value = line.replace('export ', '', 1).strip().split('=', 1)
else:
try:
key, value = line.strip().split('=', 1)
except ValueError:
logging.error(f"envar_utils.get_envvars error parsing line: '{line}'")
raise
if set_environ and key not in exclude_override:
os.environ[key] = value
if key in exclude_override:
env_vars.append({'name': key, 'value': os.getenv(key)})
else:
env_vars.append({'name': key, 'value': value})
except FileNotFoundError:
if not ignore_not_found_error:
raise
return env_vars
def create_envvar_file(env_file_path, envvars):
"""
Writes envvar file using env var dict
:param env_file_path: str, path to file to write to
:param envvars: dict, env vars
:return:
"""
with open(env_file_path, "w+") as f:
for key, value in envvars.items():
f.write("{}={}\n".format(key, value))
return True
def convert_env_var_flag_to(env_var_name, required_type, default_value):
"""
Convert env variable string flag values to required_type
:param env_var_name: str, environment variable name
:param required_type: str, required type to cast the env var to
:param default_value: boolean, default value to use if the environment variable is not available
:return: environment variable value in required type
"""
env_var_orginal_value = os.getenv(env_var_name, default_value)
env_var_value = ""
try:
if required_type == INT_TYPE:
env_var_value = int(env_var_orginal_value)
elif required_type == FLOAT_TYPE:
env_var_value = float(env_var_orginal_value)
elif required_type == BOOLEAN_TYPE:
env_var_value = bool(int(env_var_orginal_value))
elif required_type == STRING_TYPE:
env_var_value = str(env_var_orginal_value)
elif required_type == LIST_TYPE:
env_var_value = env_var_orginal_value.split(',') if len(env_var_orginal_value) > 0 else default_value
elif required_type == DICT_TYPE:
try:
env_var_value = json.loads(env_var_orginal_value) if env_var_orginal_value else default_value
except Exception as e:
logging.error(f"convert_env_var_flag_to: failed loading {env_var_orginal_value} error {e}")
env_var_value = default_value
else:
logging.error("Unrecognized type {} for env var {}".format(required_type, env_var_name))
except ValueError:
env_var_value = default_value
logging.warning("{} is {}".format(env_var_name, env_var_orginal_value))
return env_var_value
를 사용할 수 있습니다. 예제는 여기에서 찾을 수 있습니다.
이 의 하만이당신의은을 합니다.key
=value
부아에존데이터 에 있을 .[heading]
예를 들어 다음과 같습니다.
[mysqld]
user = mysql # Key with values
pid-file = /var/run/mysqld/mysqld.pid
skip-external-locking
old_passwords = 1
skip-bdb # Key without value
skip-innodb
Dewald Abrie는 좋은 해결책을 게시했습니다.
브레이크라인을 무시하는 의 수정이 \n
)
def get_env_data_as_dict(path: str) -> dict:
with open(path, 'r') as f:
return dict(tuple(line.replace('\n', '').split('=')) for line
in f.readlines() if not line.startswith('#'))
print(get_env_data_as_dict('../db.env'))
좀 더 콤팩트한 솔루션의 경우 다음과 같습니다.
import os
with open('.docker-compose-env', 'r') as fh:
vars_dict = dict(
tuple(line.replace('\n', '').split('='))
for line in fh.readlines() if not line.startswith('#')
)
print(vars_dict)
os.environ.update(vars_dict)
python std만 사용
import re
envre = re.compile(r'''^([^=]+)\s+?=\s+?(?:[\s"']*)(.+?)(?:[\s"']*)$''')
result = {}
with open('/etc/os-release') as ins:
for line in ins:
match = envre.match(line)
if match is not None:
result[match.group(1)] = match.group(2)
당신을 위해 환경을 관리하는 외부 도구에 맡겨야 한다고 생각합니다.
이렇게 하면 암호화된 볼트에서 환경 변수를 로드하기 위해 1password cli와 같은 비밀 관리자를 쉽게 사용할 수 있습니다.
op run --env-file=.env -- python your_script.py
말을 듣고 그대로.load_dotenv
환경에 존재하지만 다른 솔루션 중 일부는 그렇지 않은 경우 .env 변수를 로드하지 않을 정도로 똑똑합니다.
외부 툴을 사용할 수 없는 경우에는 'bash'를 사용하십시오.
set -o allexport; source .env; set +o allexport
솔루션의 출처:키/값 쌍의 파일에서 환경 변수 설정
python-decouple은 이러한 유형의 파일에 적합한 옵션입니다.종종 django 응용 프로그램에 사용되지만 임의의 환경 파일에 대해서는 확장이 가능합니다.
from decouple import Config, RepositoryEnv
env=Config(RepositoryEnv('.env'))
env.get('DB_ADDR') #=> 'rethinkdb'
env.get('DB_PORT') #=> '28015'
env.get('DB_NAME') #=> 'ipercron'
python-dotenv를 사용할 수 없는 상황에서는 다음과 같은 것을 사용했습니다.
import os
def load_env_file(dotenv_path, override=False):
with open(dotenv_path) as file_obj:
lines = file_obj.read().splitlines() # Removes \n from lines
dotenv_vars = {}
for line in lines:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", maxsplit=1)
dotenv_vars.setdefault(key, value)
if override:
os.environ.update(dotenv_vars)
else:
for key, value in dotenv_vars.items():
os.environ.setdefault(key, value)
지정된 파일을 읽고 "=" 기호가 있는 줄을 구문 분석합니다.기호 앞의 값이 키가 되고 이후의 값이 값이 됩니다.
하는 현재 env 파일과 수 . v-center Single Sign On 파일과 동일한 키를 사용할 수 있습니다.override
명령어
저는 직접 읽는 것을 추천하지 않습니다..env
파일을 저장할 수 있습니다.12개 요소 앱의 구성 부분의 아이디어는 환경 변수에서 구성을 읽는 것입니다. 즉, 파일에서가 아닙니다.
.env
파일은 이러한 변수를 환경으로 가져오는 편리한 방법입니다(아래 참조).코드에서 직접 파일을 읽기 시작하면 환경 변수에 대한 이 단계를 단축할 수 있으며 기본적으로 원점으로 돌아가 파일에서 구성을 읽습니다.
그래서 당신이 대신 해야 할 일은 다음과 같은 dotenv-cli와 같은 도구를 사용하십시오..env
파일을 사용하여 변수를 환경으로 내보내고 다음과 같이 임시로 수정된 환경으로 앱을 실행합니다.
$ dotenv yourapp
저는 이것이 그다지 자랑스럽지는 않지만, 다른 답변과 달리 (같은 줄의 데이터 뒤에) 주석으로 끝나는 줄이 있으면 효과가 있는 것 같습니다.@Tom의 대답을 각색했습니다.
# have to parse manually since dotenv package is not available
def get_env_data_as_dict(dotenv_path):
result = {}
with open(dotenv_path) as file_obj:
lines = file_obj.read().splitlines() # Removes \n from lines
for line in lines:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
if "#" in line:
line = line.split("#")[0].strip()
key, value = line.split("=", maxsplit=1)
result[key] = value
return result
주피터 노트북을 사용하는 경우 이 마법을 사용하여 다음을 가리킬 수 있습니다..env
java.
%reload_ext dotenv
%dotenv path/to/env_vars.env
설명서는 여기에 있습니다.
언급URL : https://stackoverflow.com/questions/40216311/reading-in-environment-variables-from-an-environment-file
'programing' 카테고리의 다른 글
8.4.0으로 버전 충돌 업데이트 (0) | 2023.09.10 |
---|---|
Windows 탐색기와 동일하게 파일 이름별로 정렬하는 방법은 무엇입니까? (0) | 2023.09.10 |
powershell을 사용하여 xml 구문 분석 (0) | 2023.09.05 |
Spring MVC와 Struts MVC의 차이 (0) | 2023.09.05 |
Oracle PL/SQL의 사용자 지정 순서 (0) | 2023.09.05 |