Skip to main content

Handle .env files with types

Project description

typed_dotenv

Parse .env files with types

Installation

pip install typed_dotenv

To use...

  • load_into: pip install typed_dotenv[pydantic]
  • YAML literals: pip install typed_dotenv[yaml]
  • TOML literals: pip install typed_dotenv[toml]

Usage

With the following .env file:

GITHUB_TOKEN="jkjkimnotputtinmygithubpersonaltokeninamodulesexamples"
DEBUG_IN_PRODUCTION=False
import typed_dotenv

secrets = typed_dotenv.load(".env")

You'll see here that nothing has changed much: secrets['DEBUG_IN_PRODUCTION'] is still a str.

That's because you need to explicitly define what syntax your .env uses. Add the following at the top of your .env:

# values: python
GITHUB_TOKEN="jkjkimnotputtinmygithubpersonaltokeninamodulesexamples"
DEBUG_IN_PRODUCTION=False

Now the following will not raise an assertion error:

import typed_dotenv

secrets = typed_dotenv.load() # ".env" is the default value
assert type(secrets["DEBUG_IN_PRODUCTION"]) is bool

We used python-style values, but other syntaxes are available:

  • values: yaml 1.2 to use YAML 1.2 literalspip install typed_dotenv[yaml]
  • values: yaml 1.1 to use YAML 1.1 literals (differences from YAML 1.2). For now, this has the same effect as values: yaml 1.2pip install typed_dotenv[yaml]
  • values: toml to use TOML literals: 12:35:24 resolves to a datetime.time, etc.pip install typed_dotenv[toml]
  • values: json to use JSON literals

Now, up until now, we've only seen how to get those variables into a dict.

The recommended way: using Pydantic's BaseModel with load_into

This way, you have IDE autcompletion and type checking, and pydantic will raise errors if the value is not of the right type:

from pydantic import BaseModel
import typed_dotenv

class Secrets(BaseModel):
    GITHUB_TOKEN: str
    DEBUG_IN_PRODUCTION: bool

secrets = typed_dotenv.load_into(Secrets, filename="my_dotenv.env")

Production usage without a dotenv file

You can also use load_into with None as the filename to load variables from the environment:

from pydantic import BaseModel
import typed_dotenv

class Secrets(BaseModel):
    GITHUB_TOKEN: str
    DEBUG_IN_PRODUCTION: bool

secrets = typed_dotenv.load_into(Secrets, filename=None)

In that case, the value syntax will always be YAML 1.2 (we need a format that allows raw strings, since env variables are unquoted).

Manually coerce from os.getenv calls

You might still want to load these values as environment variables, but need to get type coersion. This time, since the value is gotten via os.getenv, typed_dotenv does not know the file's contents. The syntax used is thus declared when coercing types:

from os import getenv
import typed_dotenv

print(os.getenv("MY_ENV_VARIABLE"))
print(
    typed_dotenv.coerce(
        os.getenv("MY_ENV_VARIABLE"),
        typed_dotenv.VALUE_FORMATS.python_literal
    )
)

You can also make yourself a function to avoid declaring the values' format each time:

def env_coerce(key: str) -> Any:
    return typed_dotenv.coerce(
        os.getenv(key),
        typed_dotenv.VALUE_FORMATS.python_literal
    )

And use it like so:

print(env_coerce("MY_ENV_VARIABLE"))

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

typed_dotenv-2.0.2.tar.gz (3.7 kB view hashes)

Uploaded Source

Built Distribution

typed_dotenv-2.0.2-py3-none-any.whl (4.1 kB view hashes)

Uploaded Python 3

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