PicoConf
PicoConf is a tiny, opinionated, lightning fast, and easy to use configuration library for Python. It is designed to be used in small to medium sized projects where a full blown configuration library is overkill.
This project is a Rust port of my NanoConf project, so inherits the usage patterns from that. However, it is roughtly 40x faster!
Installation
uv pip install picoconf
Usage
from picoconf import PicoConf
# or if PicoConf if too long of a name
from picoconf import PC
# Create a new configuration object
config = PicoConf("/path/to/config.pconf")
# Access config values using dictionary-style access
print(config["some_key"])
# Or use dotted attribute access (recommended for cleaner code)
print(config.some_key)
# Both methods work interchangeably
assert config["some_key"] == config.some_key
# Nested values support both access methods too
print(config.database.host) # attribute access
print(config["database"]["host"]) # dictionary access
# Convert to plain Python dict (recursively)
plain_dict = config.to_dict()
# All nested PicoConf objects become regular dicts
Key Normalization
PicoConf is opinionated: all config keys are normalized to lowercase regardless of how they are defined. This applies to keys loaded from .pconf files, kwargs passed to the constructor, and keys introduced via environment variable overrides. It ensures consistent, cross-platform behavior (Windows treats environment variable names as case-insensitive).
# Keys are always stored and accessed in lowercase
config = PC(**{"LOG_LEVEL": "debug", "Database_Host": "localhost"})
print(config.log_level) # "debug"
print(config.database_host) # "localhost"
Always use lowercase when reading config values, even if the source uses uppercase or mixed case.
Configuration File Format
PicoConf uses a simple configuration file format that is easy to read and write. Each File is YAML formatted and contains a single top-level dictionary. Even though the top-level must be a dictionary, you can nest dictionaries and lists as deep as you want. Each config file also must have the .pconf extension. This ensures that PicoConf will only load files that are meant to be configuration files.
key: value
test: 1
overriden: false
things:
- thing1
- thing2
- thing3
top:
v1: 1
middle:
v2: 2
inner:
v3: 3
deep:
v4: 4
If you have multiple config files you want to load into a single config object, you can put them all in the same directory and pass that directory to PicoConf. PicoConf will automatically place sub-files by their filename as an attribute of the parent file. The contents of that file will be accessible as you'd expect under the corresponding filename attribute.
<project root>
conf_dir
|__ cfg1.pconf
|__ cfg2.pconf
|__ cfg3.pconf
# load an entire directory
proj_config = PicoConf("/path/to/conf_dir")
print(proj_config.cfg1.test)
Or you can import additional files or directories from within any config file by using the _import keyword.
# main.pconf
_import:
- /path/to/project/more_config
key: value
test: 1
<project root>
main.pconf
more_config
|__ subcfg1.pconf
|__ subcfg2.pconf
|__ subcfg3.pconf
# loading the main config file will also load the sub-configs
proj_config = PicoConf("/path/to/project/main.pconf")
print(proj_config.more_config.subcfg1.test)
Notice how the directory structure was also maintained in the attribute path. This makes it easier to find the file that a value came from.
Environment Variables
PicoConf supports environment variables either as overrides to existing values or as additions to the loaded config.
Envars are evaluated on a per-file basis, so you can have different envars for different config files.
The way we manage this is by having a special _envar_prefix key in the config file.
Because all keys are normalized to lowercase (see above), env var suffixes are matched case-insensitively by design — MYAPP_LOG_LEVEL and myapp_log_level both map to the log_level config key.
_envar_prefix: myapp
key: value
overrideme: original
export myapp_overrideme=changed
config = PicoConf("/path/to/config.pconf")
print(config.overrideme)
You can also pass complex data structures as JSON strings in environment variables.
export myapp_abc='{"a": 1, "b": 2, "c": 3}'
config = PicoConf("/path/to/config.pconf")
print(config.abc.b)
Overriding Individual Keys in Nested Sections
Because env vars are matched flat against each file's own prefix, there is no built-in delimiter (like __) for drilling into a nested section. The idiomatic way to get per-key env var control over a nested section is to split that section into its own file with its own _envar_prefix, then import it from the parent.
<project root>
main.pconf
connection.pconf
connection.pconf — owns the prefix for its own keys:
_envar_prefix: myapp_connection
host: db.example.com
port: 5432
main.pconf — imports the file so the nesting is preserved:
_envar_prefix: myapp
_import:
- connection.pconf
key: value
config = PicoConf("/path/to/main.pconf")
print(config.connection.host) # db.example.com
Now individual keys in the nested section can be overridden without touching the rest:
export myapp_connection_host=prod-db.example.com
The access path (config.connection.host) stays the same — picoconf nests the imported file under its filename, so the structure is identical to having the values inline in main.pconf.
Converting to Plain Dictionaries
PicoConf objects can be recursively converted to plain Python dictionaries using the to_dict() method. This is useful for serialization, passing to libraries that expect plain dicts, or API responses.
config = PicoConf("/path/to/config.pconf")
# Convert entire config to plain dict
plain = config.to_dict()
# All nested PicoConf objects become regular dicts
assert isinstance(plain, dict)
assert not isinstance(plain, PicoConf)
# Works with deeply nested structures
if "database" in config:
db_dict = config.database.to_dict()
# Can now be serialized to JSON, YAML, etc.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file picoconf-0.4.0.tar.gz.
File metadata
- Download URL: picoconf-0.4.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6553437680ac49e3e2c76cffd6662491fac69a61c1782cd95c29642d3a6fab30
|
|
| MD5 |
483f8876b809edb1cf12748e7494e604
|
|
| BLAKE2b-256 |
5bbe98388b8aa0d063bff45df6bf62a2843f0f03a12a81f038eabf9b8e03af46
|
File details
Details for the file picoconf-0.4.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: picoconf-0.4.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 301.2 kB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96da79b422528689415124c696cae8653154ed88c4a58173033bc67b789942b1
|
|
| MD5 |
bfa8b3f67b2e5853995419e63c1387d2
|
|
| BLAKE2b-256 |
d6d16746f7f01b0fa266f22395a8f633328ca554b894942ec2e0f20f609b6db5
|
File details
Details for the file picoconf-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: picoconf-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 439.7 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89b8a10de56330e08fb930e7a23800a53ad9bf987aed30d538ac57c160be5017
|
|
| MD5 |
ddc07b2ac3fc343b789b8f5bd9497555
|
|
| BLAKE2b-256 |
c9663fb53f1ac4f3518ec63a7e4d4e53c5e4791ad70d2cf1d96d34b2c6c01bdd
|
File details
Details for the file picoconf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: picoconf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 428.7 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
158aeed1157ec31e6ed957c56d90059d49c75c37998f20eafb65f02fabc9736f
|
|
| MD5 |
a0066a4ff2422259e93cb3de92b7a441
|
|
| BLAKE2b-256 |
2777122d3e76203bd4c5c8f9b618977a621941083a1d225bd271cec471e474e6
|
File details
Details for the file picoconf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: picoconf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 392.2 kB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3aec0462d514ef1ca750d39478473298dbe61f32afa17a3f74c750a1cad92e37
|
|
| MD5 |
05f3684163a2441c827b7e7a16b6b618
|
|
| BLAKE2b-256 |
c49944ea413ae491a8753470d2f49222ca93a7085570a10dc70772cc46d178ce
|
File details
Details for the file picoconf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: picoconf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 406.9 kB
- Tags: CPython 3.11+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b4b58329ec760a5a23143ec94b91f2dd4232e6be57d211b6749a34b6920bf7f
|
|
| MD5 |
77996bfa85e5466e7192a029d99d3a4e
|
|
| BLAKE2b-256 |
1b3e7b7b49d141b96c4b5e640550156d74ca21ee223ee5bf386818aa566b00b3
|