Skip to main content

Configuration file parsing with argparse.

Project description

Python version PyPI version code style: black

Parse configuration files with argparse. Built-in support for type validation and argument nesting.

Contributions and feedback welcome! 🤝

Supported file types

Files are safely loaded and validated with tried and tested libraries.

type validator third-party note
argparse no
cfg configparser no
ini configparser no
json json no
toml toml yes tomllib is built-in from Python 3.11
yaml pyyaml yes

Installation

pip install cargparse

Basic usage

Given config.yaml...

text: hello world
decimal: 0.5
boolean: False

...just use argparse as you normally would...

import argparse
import cargparse

parser = argparse.ArgumentParser()
parser.add_argument('--text', type=str)
parser.add_argument('--decimal', type=float)
parser.add_argument('--boolean', type=lambda x: eval(x))
config = cargparse.Parser(parser).parse_file('config.yaml')

...to get the familiar Namespace object!

>> config
Namespace(text='hello world', decimal=0.5, boolean=False)
>> config.text
'hello world'
>> type(config.decimal)
<class 'float'>

Advanced usage

You are not restricted to a flat hierarchy.

model:
  lstm:
    input_size: 100
    hidden_size:
      - 128
      - 64
  summary: True

Define a helper function to parse each nested dictionary args, which is a valid dictionary str.

def parse_config(filename: Path | str) -> cargparse.Namespace:

    def model_namespace(args: str) -> cargparse.Namespace:
        parser = argparse.ArgumentParser()
        parser.add_argument('--cnn', type=cnn_namespace)
        parser.add_argument('--lstm', type=lstm_namespace)
        parser.add_argument('--summary', type=lambda x: eval(x))
        return cargparse.Parser(parser).parse_args(args)

    def cnn_namespace(args: str) -> cargparse.Namespace:
        parser = argparse.ArgumentParser()
        parser.add_argument('--in_channels', type=int, required=True)
        parser.add_argument('--out_channels', type=int, required=True)
        parser.add_argument('--kernel_width', type=int, required=True)
        return cargparse.Parser(parser).parse_args(args)

    def lstm_namespace(args: str) -> cargparse.Namespace:
        parser = argparse.ArgumentParser()
        parser.add_argument('--input_size', type=int, required=True)
        parser.add_argument('--hidden_size', type=lambda x: eval(x), required=True)
        return cargparse.Parser(parser).parse_args(args)

    parser = argparse.ArgumentParser()
    parser.add_argument('--model', type=model_namespace, required=True)
    return cargparse.Parser(parser).parse_file(filename)

if __name__ == '__main__':
    config = parse_config(filename=sys.argv[1])

Nested dictionaries are Namespace objects, too! 🌈

>> config.model.cnn
>> config.model.lstm.hidden_units
*** AttributeError: hidden_units not in namespace: ['input_size', 'hidden_size']
>> config.model.lstm.hidden_size
[128, 64]

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

cargparse-0.0.8.tar.gz (4.9 kB view hashes)

Uploaded Source

Built Distribution

cargparse-0.0.8-py3-none-any.whl (5.0 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