Skip to main content

gConfigs

Configuration helper for Python applications.

gConfigs provides a unified API to read configuration values from different sources:

  • Environment variables
  • Dotenv files
  • INI files
  • TOML files
  • Local mounted files in a directory
  • Individual local files

Why another config library?

I made it for myself. That's it.

Installation

Python 3.11+

pip install gconfigs

or with uv:

uv add gconfigs

Or even better. It's small enough, avoid the dependency entirely, and copy gconfigs/ into your project.

Extra effort to convince you to avoid dependencies: maybe all you need is just os.environ.

Quick Start

import gconfigs

# 1) Environment variables
envs = gconfigs.envs()
debug = envs("DEBUG", default=False, cast=bool)
home = envs("HOME", default="/")

# 2) Mounted directory (for configs or secrets)
configs = gconfigs.local_files("/run/configs")
language_code = configs("LANGUAGE_CODE", default="en-us")

# 3) Single local file
secrets = gconfigs.local_file()
db_password = secrets("/run/secrets/DB_PASSWORD")

# 4) Dotenv file
dotenvs = gconfigs.dotenvs(".env")
project_name = dotenvs("PROJECT_NAME", default="my-app")

# 5) INI file
ini = gconfigs.ini_file("./config/settings.ini")
app_name = ini("app.name", default="my-app")

# 6) TOML file
toml = gconfigs.toml_file("./config/settings.toml")
db_port = toml("database.port", cast=int)

API Overview

The package exposes six factory functions:

  • gconfigs.envs() -> reads from process environment variables
  • gconfigs.dotenvs(filepath=".env") -> reads from dotenv files
  • gconfigs.ini_file(filepath=".ini") -> reads from INI files using section.option keys
  • gconfigs.toml_file(filepath=".toml") -> reads from TOML files using dotted keys
  • gconfigs.local_files(path="/run/configs", pattern="*") -> reads from files in a directory
  • gconfigs.local_file() -> reads from a single file path provided at call time

Each factory returns a GConfigs instance.

Main call signature:

GConfigs.get(key, *, default=NOTSET, use_instead=NOTSET, strip=None, cast=None, list_sep=None, bool_values=None, **backend_kwargs)

Usage

Environment Variables

import gconfigs

envs = gconfigs.envs()

home = envs("HOME")
workers = envs("WORKERS", default="2", cast=int)
debug = envs("DEBUG", default=False, cast=bool)

Dotenv Files

import gconfigs

dotenvs = gconfigs.dotenvs("./config/.env")
dsn = dotenvs("DATABASE_DSN")

# load another dotenv file with a different GConfigs instance
other = gconfigs.dotenvs("./config/another.env")

INI Files

import gconfigs

ini = gconfigs.ini_file("./config/settings.ini")

app_name = ini("app.name")
db_host = ini("database.host")
db_port = ini("database.port", cast=int)

INI parser behavior:

  • Keys use section.option format
  • Values are read as strings by default
  • Use cast to convert values
  • Missing section/option raises KeyError

TOML Files

import gconfigs

toml = gconfigs.toml_file("./config/settings.toml")

app_name = toml("name")
db_host = toml("database.host")
db_port = toml("database.port", cast=int)
pool_size = toml("database.pool.size", cast=int)

TOML parser behavior:

  • Keys use dotted access for nested tables
  • Values preserve native TOML types (e.g. int, bool, list)
  • Missing nested keys raise KeyError

Dotenv parser behavior:

  • Ignores lines starting with #, ;, and [section]
  • Ignores lines without =
  • Splits at the first = so values can contain =
  • Strips key whitespace
  • Preserves value whitespace (except trailing newline characters)
  • Last duplicated key wins

Local Mounted Files (Directory)

import gconfigs

configs = gconfigs.local_files("/run/configs")
secrets = gconfigs.local_files("/run/secrets")

api_url = configs("API_URL")
api_key = secrets("API_KEY")

How it works:

  • Relative file path is the config key
  • File content is the config value
  • Optional pattern argument filters which files are considered
  • Keys are file names directly inside the configured base path
  • Reads are restricted to the configured base path (path traversal like ../secret is blocked)
  • Recursive access is intentionally not supported (nested paths like nested/key.txt are rejected)
only_app = gconfigs.local_files("/run/configs", pattern="APP_*")

* Uses fnmatch for pattern matching. fnmatch docs

Single Local File

import gconfigs

secrets = gconfigs.local_file()
token = secrets("/run/secrets/SERVICE_TOKEN")

Common Patterns

Default Value

port = envs("PORT", default="8000")

Fallback Key with use_instead

host = envs("SERVICE_HOST", use_instead="HOST", default="127.0.0.1")

Strip Control

By default, returned string values are stripped.

value = envs("MY_KEY")  # strip=True by default
raw_value = envs("MY_KEY", strip=False)

Type Casting

Use cast in GConfigs.get (or by calling the instance directly) to convert values.

Boolean

  • Accepts native bool values
  • Accepts case-insensitive string pairs from bool_values
  • Default bool_values pairs:
    • ("true", "false")
    • ("1", "0")
    • ("yes", "no")
    • ("y", "n")
    • ("on", "off")
debug = envs("DEBUG", default=False, cast=bool)
feature_enabled = envs(
    "FEATURE_X",
    cast=bool,
    bool_values=(("enabled", "disabled"),),
)

list, tuple, and set

  • Accepts native iterable values for conversion between list/tuple/set
  • Accepts JSON-style list strings like "[1, 2, 3]"
  • Accepts separator-delimited strings using list_sep
hosts = envs("ALLOWED_HOSTS", cast=list)
hosts_csv = envs("ALLOWED_HOSTS_CSV", cast=list, list_sep=",")
hosts_pipe = envs("ALLOWED_HOSTS_PIPE", cast=list, list_sep="|")

coords = envs("COORDS", cast=tuple)
labels = envs("LABELS", cast=set)

dict

  • Accepts native dict values
  • Accepts JSON-style object strings like "{"workers": 2}"
options = envs("APP_OPTIONS", cast=dict)

Custom cast function or type

from decimal import Decimal

price = envs("PRICE", cast=Decimal)


def normalize_slug(value):
    return str(value).strip().lower().replace(" ", "-")


slug = envs("PROJECT_NAME", cast=normalize_slug)

Output Formatting with ValueOutput

GConfigs delegates output conversion and strip behavior to ValueOutput.

Default behavior:

  • strip=True
  • list_sep=","
  • bool_values as described in the casting section

You can pass a custom ValueOutput instance to GConfigs:

from gconfigs.gconfigs import GConfigs, ValueOutput


class DictBackend:
    def __init__(self):
        self.data = {"DEBUG": "enabled", "HOSTS": "a|b|c"}

    def keys(self):
        return self.data.keys()

    def get(self, key, **backend_kwargs):
        if key not in self.data:
            raise KeyError(f"{key} not set")
        return self.data[key]


output_fmt = ValueOutput(list_sep="|", bool_values=(("enabled", "disabled"),))
configs = GConfigs(backend=DictBackend, output_fmt=output_fmt)

debug = configs("DEBUG", cast=bool)
hosts = configs("HOSTS", cast=list)

Iteration and Utilities

GConfigs implements container and iterator protocols.

import gconfigs

envs = gconfigs.envs()

if "HOME" in envs:
    print("HOME exists")

print(len(envs))

for item in envs:
    print(item.key, item.value)

print(envs.json())

Notes:

  • Iteration yields namedtuples with key and value fields
  • Use .iterator() when you need a fresh independent iterator

Error Behavior

Typical exceptions you may see:

  • KeyError for missing environment variable or missing dotenv key
  • FileNotFoundError for missing paths/files in file backends
  • PermissionError for unreadable files in local_file backend
  • ValueError for invalid cast values

Use default=... to avoid exceptions for missing keys when appropriate.

Custom Backend

You can plug your own backend into GConfigs.

Required backend methods:

  • get(key: str, **backend_kwargs)
  • keys()

Example:

from gconfigs.gconfigs import GConfigs


class DictBackend:
    def __init__(self):
        self.data = {"NAME": "my-app", "DEBUG": "false"}

    def additional_method(self):
        return "This is an additional method in the backend class."

    def keys(self):
        return self.data.keys()

    def get(self, key, **backend_kwargs):
        if key not in self.data:
            raise KeyError(f"{key} not set")
        return self.data[key]


configs = GConfigs(backend=DictBackend)
name = configs("NAME")
debug = configs("DEBUG", cast=bool)

# You can access the backend instance directly from GConfigs instance
assert configs.backend.additional_method

License

MIT. See LICENSE-MIT.

Release files for gconfigs 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gconfigs 2.0.0
File Size Uploaded
gconfigs-2.0.0.tar.gz 10.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gconfigs 2.0.0
File Interpreter ABI Platform
gconfigs-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.2 kB

Release files / gconfigs-2.0.0.tar.gz

Download URL gconfigs-2.0.0.tar.gz
Size 10.4 kB
Tags Source
SHA-256 checksum
How to use checksums
75706094120d0e2f462e3ed59ed4b7a57f8b0b71d03f8995a88e57123be61a75
BLAKE2b-256 checksum
How to use checksums
6ebc6d37d42c3b130aa1d18650bb51c538deb78fc49b46f1a8200c4f262bc500
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Release files / gconfigs-2.0.0-py3-none-any.whl

Download URL gconfigs-2.0.0-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f48b98b33336c1af0e6cd3294bc007424a63e9d5fd3e4958aa2ce46dbb814e9c
BLAKE2b-256 checksum
How to use checksums
2bd5548764c429e70ecbb347d6bb8c9960cebc68d8197e214700e2f5323ba6db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page