Get argument names from a parser, without parsing arguments in argparse python - python

I have the following argument parser in a python script make_parser.py :
import argparse
parser = argparse.ArgumentParser(
description='Multiplies the input <n> by <m>'
)
parser.add_argument(
'n', type=float, help='Input number to be multiplied'
)
parser.add_argument(
'-m', '--optional-multiplier',
type=float, default=1,
help='multiplier for <n> : (default: 1)'
)
How do I get the positional and optional argument names and their details, possibly as some object, or just as a dict.
For e.g., some method like parser.get_positional_args
>>> from make_parser import parser
>>> parser.get_positional_args()
<argparse.ArgumentClass object at 0x7f3871721e80>
And the same for optional arguments, something like parser.get_optional_args

Add to your code:
for action in parser._actions:
print(action)
print([(action.dest, action.option_strings) for action in parser._actions])
print([action.dest for action in parser._actions if not action.option_strings])
print([action.dest for action in parser._actions if action.option_strings])
result (edited for clarity):
0848:~/mypy$ python3 stack57450629.py
_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None)
_StoreAction(option_strings=[], dest='n', nargs=None, const=None, default=None, type=<class 'float'>, choices=None, help='Input number to be multiplied', metavar=None)
_StoreAction(option_strings=['-m', '--optional-multiplier'], dest='optional_multiplier', nargs=None, const=None, default=1, type=<class 'float'>, choices=None, help='multiplier for <n> : (default: 1)', metavar=None)
[('help', ['-h', '--help']), ('n', []), ('optional_multiplier', ['-m', '--optional-multiplier'])]
['n']
['help', 'optional_multiplier']

Related

SystemExit 2 error in the compilation of code when calling -e', '--episode', type=int, default=2000,

my code is a below:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-e', '--episode', type=int, default=2000,
help='number of episode to run')
parser.add_argument('-b', '--batch_size', type=int, default=32,
help='batch size for experience replay')
parser.add_argument('-i', '--initial_invest', type=int, default=20000,
help='initial investment amount')
parser.add_argument('-m', '--mode', type=str, required=True,
help='either "train" or "test"')
parser.add_argument('-w', '--weights', type=str, help='a trained model weights')
args = parser.parse_args()
maybe_make_dir('weights')
maybe_make_dir('portfolio_val')
Error:-
usage: [-h] [-e EPISODE] [-b BATCH_SIZE] [-i INITIAL_INVEST] -m MODE
[-w WEIGHTS]
: error: the following arguments are required: -m/--mode
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
So in the above error i am not able to understand what is the mistake i have also imported all the libraries correctly.
try changing this:
parser.add_argument('-m', '--mode', type=str, required=True,
help='either "train" or "test"')
to this: (notice nargs and const)
parser.add_argument('-m', '--mode',nargs='?', const='' , type=str, required=True,
help='either "train" or "test"')
then you can add this to your code:
if len(args.mode) == 0:
print('-m either "train" or "test"')
import sys
sys.exit() #closes python script
as explained here: https://stackoverflow.com/a/58396626/13093413

python argparse different parameters with different number of arguments

How do I use a different number of parameters for each option?
ex) a.py
parser.add_argument('--opt', type=str,choices=['a', 'b', 'c'],help='blah~~~')
choice : a / parameter : 1
ex)
$ python a.py --opt a param
choice : c / parameter :2
ex)
$ python a.py --opt b param1 param2
You need to add sub-commands, ArgumentParser.add_subparsers() method will help you
Check this example
>>> # create the top-level parser
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', action='store_true', help='foo help')
>>> subparsers = parser.add_subparsers(help='sub-command help')
>>>
>>> # create the parser for the "a" command
>>> parser_a = subparsers.add_parser('a', help='a help')
>>> parser_a.add_argument('bar', type=int, help='bar help')
>>>
>>> # create the parser for the "b" command
>>> parser_b = subparsers.add_parser('b', help='b help')
>>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
>>>
>>> # parse some argument lists
>>> parser.parse_args(['a', '12'])
Namespace(bar=12, foo=False)
>>> parser.parse_args(['--foo', 'b', '--baz', 'Z'])
Namespace(baz='Z', foo=True)
You may add more parameters, one for each a, b, and c and also optional arguments for your params. By using the named parameter nargs='?' you can specify that they are optional and with the default="some value" you ensure it rises no errors. Finally, based on the selected option, a,b or c you will be able to capture the ones you need.
Here's a short usage example:
parser.add_argument('x1', type=float, nargs='?', default=0, help='Circ. 1 X-coord')
parser.add_argument('y1', type=float, nargs='?', default=0, help='Circ. 1 Y-coord')
parser.add_argument('r1', type=float, nargs='?', default=70, help='Circ. 1 radius')
parser.add_argument('x2', type=float, nargs='?', default=-6.57, help='Circ. 2 X-coord')
parser.add_argument('y2', type=float, nargs='?', default=7, help='Circ. 2 Y-coord')
parser.add_argument('r2', type=float, nargs='?', default=70, help='Circ. 2 radius')
args = parser.parse_args()
circCoverage(args.x1, args.y1, args.r1, args.x2, args.y2, args.r2)
here, if no values are selected, the default ones are used. You can play with this to get what you want.
Cheers

How to disable an argument if another is present?

In my script argparse there are some arguments that will conflict if another argument of opposite kind is passed. I want to disable the --arg2 if --arg1 is already present. Currently I haven't found any way to do so.
Use a mutually exclusive group:
parser = argparse.ArgumentParser(prog='PROG')
group = parser.add_mutually_exclusive_group()
group.add_argument('--arg1')
group.add_argument('--arg2')
Only one argument in the group is allowed to be used.
Demo:
>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('--arg1')
_StoreAction(option_strings=['--arg1'], dest='arg1', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> group.add_argument('--arg2')
_StoreAction(option_strings=['--arg2'], dest='arg2', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--arg1', 'foo'])
Namespace(arg1='foo', arg2=None)
>>> parser.parse_args(['--arg2', 'bar'])
Namespace(arg1=None, arg2='bar')
>>> parser.parse_args(['--arg1', 'foo', '--arg2', 'bar'])
usage: PROG [-h] [--arg1 ARG1 | --arg2 ARG2]
PROG: error: argument --arg2: not allowed with argument --arg1

Option accepted with and without value

I have a small script and I need it to be able to accept parameter with value and withou value.
./cha.py --pretty-xml
./cha.py --pretty-xml=5
I have this.
parser.add_argument('--pretty-xml', nargs='?', dest='xml_space', default=4)
But when I use --pretty-xml in xml_space will be 'none'. If I dont write this parameter in xml_space is stored the default value. I would need the exact opposite.
Use the const keyword:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--pretty-xml", nargs="?", type=int, dest="xml_space", const=4)
print(parser.parse_args([]))
print(parser.parse_args(['--pretty-xml']))
print(parser.parse_args(['--pretty-xml=5']))
results in
Namespace(xml_space=None)
Namespace(xml_space=4)
Namespace(xml_space=5)
Leave out the default parameter and use a custom Action instead:
class PrettyXMLAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if not values:
values = 4
setattr(namespace, self.dest, values)
parser.add_argument('--pretty-xml', nargs='?', type=int, dest='xml_space', action=PrettyXMLAction)
Demo:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--pretty-xml', nargs='?', type=int, dest='xml_space', action=PrettyXMLAction)
PrettyXMLAction(option_strings=['--pretty-xml'], dest='xml_space', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--pretty-xml'.split())
Namespace(xml_space=4)
>>> parser.parse_args('--pretty-xml=5'.split())
Namespace(xml_space=5)
>>> parser.parse_args(''.split())
Namespace(xml_space=None)

python - argparse one argument instead of several others

For example I have options:
parser.add_argument('-b', action="store_true")
parser.add_argument('-c', action="store_true")
parser.add_argument('-d', action="store_true")
I want to enable all of them with synonym option "-a". Is it possible?
I think it is simplest to do this after parse_args():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b', action="store_true")
parser.add_argument('-c', action="store_true")
parser.add_argument('-d', action="store_true")
parser.add_argument('-a', action="store_true")
args = parser.parse_args()
if args.a: args.b = args.c = args.d = True
Alternatively, you could do it with a custom action, but I think it is overkill:
import argparse
class AllAction(argparse.Action):
def __call__(self, parser, args, values, option_string = None):
# print '{n} {v} {o}'.format(n = args, v = values, o = option_string)
for param in ['a', 'b', 'c', 'd']:
setattr(args, param, True)
parser = argparse.ArgumentParser()
parser.add_argument('-b', action="store_true")
parser.add_argument('-c', action="store_true")
parser.add_argument('-d', action="store_true")
parser.add_argument('-a', action = AllAction, nargs = '?')
args = parser.parse_args()
print(args)

Categories