How to load environment variables in a config.ini file?
Asked Answered
C

3

9

I have a config.ini file which contains some properties but I want to read the environment variables inside the config file.

[section1]
 prop1:(from envrinment variable) or value1

Is this possible or do I have to write a method to take care of that?

Came answered 16/11, 2018 at 0:17 Comment(2)
@RoryDaulton - not a duplicate! That one read the values from ini file whereas I want to read the environment values in ini file. So that I can switch to default if env variables aren't available.Came
This question is perfectly clear to me as a Linux programmer. A Linux "environment variable" is a name-value binding provided by linux -- for example, the response to printenv FOOBAR from a command line. I think this question is "How do I use the value of a (Linux) system environment variable inside a a Python config file?".Gisarme
S
9

I know this is late to the party, but someone might find this handy. What you are asking after is value interpolation combined with os.environ.

Pyramid?

The logic of doing so is unusual and generally this happens if one has a pyramid server, (which is read by a config file out of the box) while wanting to imitate a django one (which is always set up to read os.environ).
If you are using pyramid, then pyramid.paster.get_app has the argument options: if you pass os.environ as the dictionary you can use %(variable)s in the ini. Not that this is not specific to pyramid.paster.get_app as the next section shows (but my guess is get_app is the case).

app.py

from pyramid.paster import get_app
from waitress import serve
import os

app = get_app('production.ini', 'main', options=os.environ)
serve(app, host='0.0.0.0', port=8000, threads=50)

production.ini:

[app:main]
sqlalchemy.url = %(SQL_URL)s
...

Configparse?

The above is using configparser basic interpolation.

Say I have a file called config.ini with the line

[System]
conda_location = %(CONDA_PYTHON_EXE)

The following will work...

import configparser, os
cfg = configparser.ConfigParser()
cfg.read('config.ini')
print(cfg.get('System', 'conda_location', vars=os.environ))
Skinner answered 13/6, 2019 at 14:31 Comment(0)
G
2

Context

I had a similar issue while using docker-compose to start up an API, a PostgreSQL DB, and also run migrations with alembic. Alembic reads the DB connection from the alembic.ini file which has:

sqlalchemy.url = postgresql://user:password@localhost:5432/db_name

In docker-compose I needed the localhost portion to reference the name of the db container instead: postgresql://user:password@db:5432/db_name

What didn't work

I tried setting the environment in docker-compose and tried setting the value in the .ini file: sqlalchemy.url = %(SQLALCHEMY_DATABASE_URL=postgresql://user:password@db:5432/db_name), but that didn't work.

What did work

What finally DID end up working was updating alembic's env.py file to read from the environment and overwrite the config value from the .ini file:

from logging.config import fileConfig
from os import environ as env
from alembic import context
...
config = context.config
if config.config_file_name is not None:
    fileConfig(config.config_file_name)
...
SQLALCHEMY_DATABASE_URL = env.get(
    "SQLALCHEMY_DATABASE_URL", "postgresql://user:password@localhost:5432/db_name"
)
config.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URL)

This reads the value from the env, if present -- if not, it uses the default localhost value. Later in the file, url is set based on the overridden env value: url = config.get_main_option("sqlalchemy.url")

Grouty answered 25/1 at 6:54 Comment(0)
A
-1

I think :thinking_face, use .env and in config.py from dotenv import load_dotenv() and in next line load_dotenv() and it will load envs from .env file

Amr answered 21/7, 2021 at 9:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.