Created
February 28, 2026 09:46
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ 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