Skip to main content

Simple environment variable parsing

Project description

envparse2 is a simple utility to parse environment variables.

NOTE: envparse2 is a fork of envparse which is no longer maintained, to check original author and code visit <https://github.com/rconradharris/envparse.git>

If you use Heroku and/or subscribe to the tenets of the 12 Factor App you’ll be using a lot of environment variable-based configuration in your app. os.environ is a great choice to start off with but over time you’ll find yourself duplicating quite a bit of code around handling raw environment variables.

envparse2 aims to eliminate this duplicated, often inconsistent parsing code and instead provide a single, easy-to-use wrapper.

Ideas, and code portions, have been taken from django-environ project but made framework agnostic.

Installing

Through PyPI:

$ pip install envparse2

Usage

In your settings or configuration module, first either import the standard parser or one with a schema:

# Standard
from envparse2 import env

# Schema
from envparse2 import Env
env = Env(BOOLEAN_VAR=bool, LIST_VAR=dict(cast=list, subcast=int))

env can then be called in two ways:

  • Type explicit: env('ENV_VAR_NAME', cast=TYPE, ...)

  • Type implicit (for Python builtin types only): env.TYPE('ENV_VAR_NAME', ...) If type is not specified, explicitly or implicitly, then the default type is str.

Casting to a specified type:

# Environment variable: MAIL_ENABLED=1

mail_enabled = env('MAIL_ENABLED', cast=bool)
# OR mail_enabled = env.bool('MAIL_ENABLED')
assert mail_enabled is True

Casting nested types:

# Environment variable: FOO=1,2,3
foo = env('FOO'), subcast=int)
# OR: foo = env('FOO', cast=list, subcast=int)
# Note that there is no way to implicitly call subcast.
assert foo == [1, 2, 3]

Specifying defaults:

# Environment variable MAX_ROWS has not been defined

max_rows = env.int('MAX_ROWS', default=100)
assert max_rows == 100

Proxying values, useful in Heroku for wiring up the environment variables they provide to the ones that your app actually uses:

# Environment variables: MAILGUN_SMTP_LOGIN=foo,
# SMTP_LOGIN='{{MAILGUN_SMTP_LOGIN}}'

smtp_login = env('SMTP_LOGIN')
assert smtp_login == 'foo'

Now if you switch to using Mandrill as an email provider, instead of having to modify your app, you can simply make a configuration change:

SMTP_LOGIN='{{MANDRILL_UESRNAME}}'

There are also a few convenience methods:

  • env.json: parses JSON and returns a dict.

  • env.url: parses a url and returns a urlparse.ParseResult object.

Type specific notes:

  • list: the expected environment variable format is FOO=1,2,3 and may contain spaces between the commas as well as preceding or trailing whitespace.

  • dict: the expected environment variable format is FOO='key1=val1, key2=val2. Spaces are also allowed.

  • json: a regular JSON string such as FOO='{"foo": "bar"}' is expected.

Schemas

Define a schema so you can only need to provide the cast, subcast, and defaults once:

# Environment variables: MAIL_ENABLED=0, LIST_INT='1,2,3'

# Bind schema to Env object to get schema-based lookups
env = Env(MAIL_ENABLED=bool, SMTP_LOGIN=dict(cast=str, default='foo'),
          LIST_INT=dict(cast=list, subcast=int))
assert env('MAIL_ENABLED') is False
assert env('SMTP_LOGIN') == 'foo' # Not defined so uses default
assert env('LIST_INT') == [1, 2, 3]

The Env constructor takes values in the form of either: VAR_NAME=type or VAR_NAME=dict where dict is a dictionary with either one or more of the following keys specified: cast, subcast, default.

Pre- and Postprocessors

Preprocessors are callables that are run on the environment variable string before any type casting takes place:

# Environment variables: FOO=bar

# Preprocessor to change variable to uppercase
to_upper = lambda v: v.upper()
foo = env('FOO', preprocessor=to_upper)
assert foo == 'BAR'

Postprocessors are callables that are run after the type casting takes place. An example of one might be returning a datastructure expected by a framework:

# Environment variable: REDIS_URL='redis://:redispass@127.0.0.1:6379/0'
def django_redis(url):
  return {'BACKEND': 'django_redis.cache.RedisCache',
      'LOCATION': '{}:{}:{}'.format(url.hostname, url.port, url.path.strip('/')),
      'OPTIONS': {'PASSWORD': url.password}}

redis_config = env('REDIS_URL', postprocessor=django_redis)
assert redis_config == {'BACKEND': 'django_redis.cache.RedisCache',
    'LOCATION': '127.0.0.1:6379:0', 'OPTIONS': {'PASSWORD': 'redispass'}}

Environment File

Read from a .env file (line delimited KEY=VALUE):

# This recurses up the directory tree until a file called '.env' is found.
env.read_envfile()

# Manually specifying a path
env.read_envfile('/config/.myenv')

# Values can be read as normal
env.int('FOO')

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

envparse2-0.3.0.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

envparse2-0.3.0-py2.py3-none-any.whl (6.8 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file envparse2-0.3.0.tar.gz.

File metadata

  • Download URL: envparse2-0.3.0.tar.gz
  • Upload date:
  • Size: 8.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for envparse2-0.3.0.tar.gz
Algorithm Hash digest
SHA256 119ea05995f6a137a02ccf1deff5b34e6dacaba79b594c5837a7879cfa3c61ce
MD5 b2c7567c7d4bb4b773f9b0f84a33499e
BLAKE2b-256 40376c8dbac240ddd65b6bb9c8519ba203afb51b67646b1630df710460cdd8d1

See more details on using hashes here.

File details

Details for the file envparse2-0.3.0-py2.py3-none-any.whl.

File metadata

  • Download URL: envparse2-0.3.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 6.8 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for envparse2-0.3.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 99a123f8ccaedf762d8f475ae802aeaa9f9699e0f4ecc3de2ec7dbe1aca1cc72
MD5 ee825dbbd6fd6855f47ebd21c4df51e9
BLAKE2b-256 09a7b084d7824a8ecc3d51cdf357dfe7263f75d1475c48fee6f0fa45e3f9881a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page