我想在本地环境中运行一个Python脚本,通常在Docker容器中运行。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'

我可以编写我的解析器,但我想知道是否有任何现有的模块/工具可以从配置文件中读取环境变量?


当前回答

我使用Python Dotenv库。只需要安装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."

当我需要在docker系统外测试代码并准备再次将其返回到docker时,我就是这样做的。

其他回答

下面是一个更紧凑的解决方案:

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-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文件中相同键的当前环境变量既可以保持不变,也可以使用override参数覆盖。

只使用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

方法:从键/值对文件中设置环境变量

我对此并不是很自豪,然而,与其他答案相比,如果一个人有以注释结尾的行(在同一行的数据之后),它似乎是有效的。改编了@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