Option accepted with and without value - python

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)

Related

argparse - how to pass argument from args into function?

import argparse
from queries import most_common_cities
parser = argparse.ArgumentParser(description='A script that does operations with database data and returns values')
parser.add_argument('-c', '--most_common_cities',
nargs=1,
type=positive_int,
help='Specify how many common cities.')
args = parser.parse_args()
if args.most_common_cities:
result = most_common_cities(n) # "n" should be an arg passed by user
print(result)
How could I pass arguments from CLI to my function arg?
When someone use command:
python argp.py --most_common_cities 5
It should return 5 most common cities.
Remove nargs=1, then args.most_common_cities will be the actual value passed in.
nargs=1 wraps it in a list.
parser.add_argument('-c', '--most_common_cities',
type=int,
help='Specify how many common cities.')
args = parser.parse_args(['-c', '5'])
n = args.most_common_cities
print(n)
print(type(n))
# 5
# <class 'int'>
I started your script with following command:
python3 test.py --most_common_cities 5
You can access the arguments with:
import argparse
parser = argparse.ArgumentParser(description='A script that does operations with database data and returns values')
parser.add_argument('-c', '--most_common_cities',
nargs=1,
type=int,
help='Specify how many common cities.')
args = parser.parse_args()
arguments = vars(parser.parse_args())
print(arguments) #{'most_common_cities': [5]}
#then you can access the value with:
arguments['most_common_cities']

Get argument names from a parser, without parsing arguments in argparse 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']

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

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