Skip to content

Instantly share code, notes, and snippets.

@DocMinus
Created February 28, 2026 09:46
Show Gist options
  • Select an option

  • Save DocMinus/56ee57e4ad2c44bf5af458f68595862a to your computer and use it in GitHub Desktop.

Select an option

Save DocMinus/56ee57e4ad2c44bf5af458f68595862a to your computer and use it in GitHub Desktop.
Py CLI parser with data classes rendering parsing simpler to implement and expand
""" CLI parser example using dataclasses. Two different approaches.
As presented by ArjanCodes https://youtu.be/Y9_h7ehjhO4?si=YrtPhBs_TXvUOv6A&t=1295
But seems to be found on GitHub or Reddit as well, so not sure if it's his original work or if he just found it somewhere else.
Doesn't matter, it's pretty helpful.
"""
import argparse
from dataclasses import dataclass, fields
from typing import Self, Type
@dataclass
class ClIArgs:
"""CLI args parser. Behavious: - All fields are required. - No default values. - No support for boolean flags."""
@classmethod
def args_from_cli(cls: Type[Self]) -> Self:
"""Parse command-line arguments and return an instance of the subclass."""
parser = argparse.ArgumentParser()
for field in fields(cls):
parser.add_argument(f'--{field.name}', type=field.type, required=True)
args = parser.parse_args()
return cls(**vars(args))
@dataclass
class CLI2Args:
"""CLI args parser. Behavious: - All fields are optional. - Default values are supported. - Boolean flags are supported
More ergonomic for users, but less strict for developers.
."""
@classmethod
def args_from_cli(cls: Type[Self]) -> Self:
"""Parse command-line arguments and return an instance of the subclass."""
parser = argparse.ArgumentParser()
for field in fields(cls):
arg_name = f'--{field.name.replace("_", "-")}'
if field.type == bool:
parser.add_argument(arg_name, action='store_true')
else:
parser.add_argument(arg_name, type=field.type, default=field.default)
args = parser.parse_args()
return cls(**vars(args))
@dataclass
class Args(ClIArgs):
example_arg: str = "default_value"
verbose: bool = False
some_number: int = 42
@dataclass
class Args2(CLI2Args):
example_arg: str = "default_value"
verbose: bool = False
some_number: int = 42
def main():
args = Args.args_from_cli()
print(args)
args2 = Args2.args_from_cli()
print(args2)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment