Package: argx
argxSupercharged argparse for PythonInstallationpipinstall-UargxFeatures enhanced or addedOptionexit_on_void: Exit with error if no arguments are providedSubcommand shortcut: Adding subcommands directly, withoutparser.add_subparsers()Namespace arguments: Access arguments like--foo.barasargs.foo.barBrief help message for massive arguments: Show only the most important arguments in the help messageDefault value in argument help: Show the default value in the help message of argumentsNewlines kept in help: Newlines are kept in argument help if anyDefaults from file: Read default values from a configuration file by API or from command lineClear-append/extend action: Store a list of values. Different fromappendandextend, the initial value is cleared.Grouping required arguments by default: Put required arguments in 'required arguments' group, instead of 'optional arguments' groupOrder of groups in help message: Allow to add anorderattribute to groups to change the order of groups in help messageAddtional types: Some additional types to convert the values of argumentsConfiguration file to create the parser: Instead of creating the parser by code, you can also create it by a configuration filePre-parse hook: A hook to modify the arguments before parsingBackward compatibility: All features are optional. You can useargxas a drop-in replacement forargparse.Optionexit_on_voidIf all arguments are optional,argparsewill not raise an error if no arguments are provided. This is not always desirable.argxprovides the optionexit_on_voidto change this behavior. Ifexit_on_voidis set toTrueand no arguments are provided,argxwill exit with an error (No arguments provided).importargxasargparseparser=argparse.ArgumentParser(exit_on_void=True)parser.add_argument('--foo',action='store_true')args=parser.parse_args([])# No arguments provided# standard argparse produces: Namespace(foo=False)Subcommand shortcutargparserequires to create subparsers first and then add the subcommands to the subparsers.argxallows to add subcommands directly to the main parser.# standard argparseparser=argparse.ArgumentParser()subparsers=parser.add_subparsers(title='subcommands')parser_a=subparsers.add_parser('a')parser_b=subparsers.add_parser('b')# argxparser=argparse.ArgumentParser()parser.add_command('a')# or parser.add_subparser('a')parser.add_command('b')# args = parser.parse_args(['a'])# Namespace(COMMAND='a')Thesubparsersis added automatically with the titlesubcommandsand thedestis set toCOMMAND. You can add subcommands to subcommands directly, then thedestis set toCOMMAND2,COMMAND3, etc. If you want to change the behavior, you can always fall back to the standardargparseway.Namespace argumentsThe values of arguments like--foo.barcan be accessed asvars(args)['foo.bar']. Withargxyou can access them asargs.foo.bar.The arguments--foo.bar,--foo.bazand--foo.quxare automatically grouped in a namespacefoo.importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo.bar',type=int)parser.add_argument('--foo.baz',type=int)parser.add_argument('--foo.qux',type=int)parser.print_help()Usage:test.py[-h][--foo.barBAR][--foo.bazBAZ][--foo.quxQUX]Optionalarguments:-h,--helpshowthishelpmessageandexitNamespace<foo>:--foo.barBAR--foo.bazBAZ--foo.quxQUXYou can modify the namespace by adding the namespace manually before adding the arguments.importargxasargparseparser=argparse.ArgumentParser()parser.add_namespace('foo',title="Foo's options")parser.add_argument('--foo.bar',type=int)parser.add_argument('--foo.baz',type=int)parser.add_argument('--foo.qux',type=int)parser.print_help()Usage:test.py[-h][--foo.barBAR][--foo.bazBAZ][--foo.quxQUX]OptionalArguments:-h,--helpshowthishelpmessageandexitFoo'sOptions:--foo.barBAR--foo.bazBAZ--foo.quxQUXYou can also add a namespace action argument to take a json that can be parsed as a dict:importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',action="namespace")# or action="ns"parser.add_argument('--foo.bar',type=int)parser.add_argument('--foo.baz',type=int)parser.add_argument('--foo.qux',type=int)parser.parse_args(['--foo','{"bar": 1, "baz": 2, "qux": 3}','--foo.qux','4'])# Namespace(foo=Namespace(bar=1, baz=2, qux=4))Brief help message for massive argumentsIf you have a lot of arguments, the help message can be very long.argxallows to show only the most important arguments in the help message.importargxasargparse# Advanced help options to show the brief help message or the full help messageparser=argparse.ArgumentParser(add_help='+')parser.add_argument('--foo',type=int)parser.add_argument('--bar',type=int,show=False)parser.parse_args(['--help'])Usage:test.py[-h][--fooFOO]OptionalArguments:-h,--help,-h+,--help+showhelpmessage(with+toshowmoreoptions)andexit--fooFOOWithparser.parse_args(['--help+'])you can show the full help message.Usage:test.py[-h][--fooFOO][--barBAR]OptionalArguments:-h,--help,-h+,--help+showhelpmessage(with+toshowmoreoptions)andexit--fooFOO--barBARYou can also setshow=Falsefor argument groups.Default value in argument helpWithargparse, the default value is not shown in the help message. Withargx, the default value is added to the help message automatically.importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',type=int,default=1)parser.add_argument('--bar',type=int,default=2,help='bar [default: two]')parser.add_argument('--baz',type=int,default=3,help='baz [nodefault]')parser.print_help()Usage:test.py[-h][--fooFOO]OptionalArguments:-h,--helpshowhelpmessageandexit--fooFOO[default:1]--barBARbar[default:two]--bazBAZbazNewlines kept in helpBy default,argparsereplaces the newlines with spaces in the argument help message. However, sometimes you want to keep the newlines. Withargx, if there is not newline, it is handled as the default behavior. If there is a newline, the newlines and spaces are kept.importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',help='foo\n- bar\nindent also kept')parser.print_help()Usage:test.py[-h][--fooFOO]OptionalArguments:-h,--helpshowthishelpmessageandexit--fooFOOfoo-barindentalsokeptDefaults from filesWith standardargparse, whenfromfile_prefix_charsis set, the arguments can be read from a file. The file can be specified with@filename. The arguments in the file are separated by newlines by default.Withargx, Other than a text file to provide command line arguments, you can also provide other types of configuration files. The extension of the file can be.json,.yaml,.ini,.envor.toml.importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',type=int)parser.add_argument('--bar',type=int)parser.add_argument('--baz',type=int)# config.json# { "foo": 1, "bar": 2, "baz": 3 }args=parser.parse_args(['@config.json'])# Namespace(foo=1, bar=2, baz=3)You can also useset_defaults_from_configsmethod:parser.set_defaults_from_configs('config.json')Clear_append/extend actionTheclear_append/clear_extendaction is similar toappendandextend, but the initial value is cleared.This is useful when you want to accept a new list of values from the command line, instead of append/extend to the existing list or default.importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',action='clear_append',default=[1,2,3],type=int)parser.add_argument('--bar',action='append',default=[1,2,3],type=int)args=parser.parse_args('--foo 4 --foo 5 --bar 4 --bar 5'.split())# Namespace(foo=[4, 5], bar=[1, 2, 3, 4, 5])Grouping required arguments by defaultBy default,argparseputs bothrequired=Trueandrequired=Falsearguments in the same group (optional arguments), which is sometimes confusing.argxgroupsrequired=Truearguments in a separate group (required arguments).importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo')parser.add_argument('--bar',required=True)parser.print_help()Usage:test.py[-h][--fooFOO]--barBAR

RequiredArguments:--barBAR

OptionalArguments:-h,--helpshowhelpmessageandexit--fooFOOOrder of groups in help messageAllow to add anorderattribute to groups to change the order of groups in help messageimportargxasargparseparser=argparse.ArgumentParser()group1=parser.add_argument_group('group1',order=2)group1.add_argument('--foo')group2=parser.add_argument_group('group2',order=1)group2.add_argument('--bar')parser.print_help()Usage:test.py[-h][--barBAR][--fooFOO]Optionalarguments:-h,--helpshowhelpmessageandexitGroup2:--barBAR

Group1:--fooFOOThe order by default is 0. The groups with the same order are sorted by title. Groups with small numbers are displayed first.required argumentshas aorderof -1.Additional typesparser.add_argument()acceptstypeas a function to convert the argument value. It has to be a callable that accepts a single string argument and returns the converted value. Whileargxsupports string fortypeso it can be configured in the configuration file. Builtin functions and types can also be specified by its name.We also have additional types:importargxasargparseparser=argparse.ArgumentParser()parser.add_argument('--foo',type='py')parser.add_argument('--bar',type='json')parser.add_argument('--baz',type='path')parser.add_argument('--qux',type='auto')args=parser.parse_args('--foo 1 --bar {"a":1} --baz path/to/file --qux true'.split())# Namespace(foo=1, bar={'a': 1}, baz=PosixPath('path/to/file'), qux=True)py: Python expression. The string is evaluated byast.literal_eval.json: JSON string. The string is loaded byjson.loads.path: Path string. The string is converted bypathlib.Path.auto: Automatic type conversion.Trueif the string isTrue/TRUE/trueFalseif the string isFalse/FALSE/falseNoneif the string isNone/NONE/noneAn integer if the string can be converted to an integerA float if the string can be converted to a floatA dict if the string is a JSON stringThe string itself otherwiseConfiguration file to create the parserYou can create the parser from a configuration file.importargxasargparse# config.json# {#   "prog": "myprog",#   "arguments": [ {"flags": ["-a", "--abc"], "help": "Optiona a help"} ]# }parser=argparse.ArgumentParser.from_configs('config.json')parser.print_help()Usage:myprog[-h][-aABC]OptionalArguments:-h,--helpshowhelpmessageandexit-aABC,--abcABCOptionaahelpPre-parse hookYou can add a pre-parse hook to the parser. The hook is called before parsing the arguments. It can be used to modify the arguments before parsing.importargxasargparsedefpre_parse(parser,args,namespace):"""We can modify the parser (i.e. add arguments)the arguments to be parsed, and even manipulate the namespace."""parser.add_argument('--foo',type=int)parser.add_argument('--bar',type=int)namespace.baz=2returnargs+["--bar","3"]parser=argparse.ArgumentParser()parser.add_command('command1',pre_parse=pre_parse)parsed=parser.parse_args('command1 --foo 1'.split())# Namespace(COMMAND='command1', baz=2, foo=1, bar=3)This is especially useful when you have a lot of subcommands and each has a lot of arguments, when it takes time to add these arguments, for example, some of the values need to be parsed from a file. Using this hook, you can add the arguments only when the subcommand is called, instead of adding them all at the beginning.Backward compatibilityAll features are optional. You can useargxas a drop-in replacement forargparse.argxsupports python3.7+. Some of the later-introduced features are also supported in python 3.7. For example,extendaction is added in python 3.8,argxsupports in python 3.7.