1

In python argparse i want to order the input by the user.

For example in the following code i want the user to enter the -x. if the user enter any other, for example -b it should show an error.

parser = argparse.ArgumentParser(description='SImple Example')    
parser.add_argument('-x', '--height', help='Height of the box')
parser.add_argument('-l', '--length', type=int, help='Length of the box')
parser.add_argument('-b', '--breadth', type=int, help='Breadth of the box')
parser.add_argument('--stop', nargs=0, required=False, action=StopAction)

while True:
    args = parser.parse_args(input("enter text: ").split())

Aleesd
  • 41
  • 8
  • Probably easier to add this validation after the fact. `if args.height and not args.breadth: raise ...` – flakes May 04 '21 at 20:32
  • So you want mutually exclusive switch? – jlandercy May 04 '21 at 20:36
  • What is the most easiest way. Can you please give an example – Aleesd May 04 '21 at 20:55
  • To where do i have to enter this. if args.height and not args.breadth: raise ... can i see the full example – Aleesd May 04 '21 at 20:56
  • Do you want to prevent the user from using `-b ... -x ...` instead of `-x ... -b ...`, or do you just want to ensure that only one of `-x`, `-l`, and `-b` is used at all? – chepner May 04 '21 at 20:58
  • 1
    Also, why are you using `argparse` to parse interactive input? It's typically meant to parse arbitrary command-line arguments. If you are just going to prompt the user for each value, you have complete control over which value are entered first: prompt for the height, then the length, and finally the breadth. If the user enters them in the wrong order, that's their problem. – chepner May 04 '21 at 21:00
  • Yes the user should first enter -x. The eemaining can be in any order. – Aleesd May 04 '21 at 21:04
  • You're asking to use the library against what it was designed and intended; a series of unsorted commandline user supplied arguments? You should find ways to fix your code rather than break the rules, imho. – NationWidePants May 27 '21 at 17:31
  • See also more complex solutions: https://stackoverflow.com/questions/9027028/argparse-argument-order – 8349697 May 27 '21 at 17:43

1 Answers1

0

Option with input

If you want to use the input function, then the following solution is possible (weird):


import argparse


class StopAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        parser.exit('Exit')

parser = argparse.ArgumentParser(description='SImple Example')    
parser.add_argument('-x', '--height', type=int, help='Height of the box')
parser.add_argument('-l', '--length', type=int, help='Length of the box')
parser.add_argument('-b', '--breadth', type=int, help='Breadth of the box')
parser.add_argument('--stop', nargs=0, required=False, action=StopAction)


values = []
for i in ['-x', '-l', '-b']:
    i_value = input(f'enter {i} value (integer): ').strip()
    if i_value == '--stop':
        parser.parse_args([i_value])
    elif i_value in ['-h', '--help']:
        parser.parse_args([i_value])
    else:
        # check for int
        parser.parse_args([i, i_value])
        values.append(i)
        values.append(i_value)

args = parser.parse_args(values)
# do something
print(args)


Output:


>test.py
enter -x value (integer): --stop
Exit

>test.py
enter -x value (integer): 1
enter -l value (integer): 2
enter -b value (integer): 3
Namespace(breadth=3, height=1, length=2, stop=None)

>test.py
enter -x value (integer): 1
enter -l value (integer): q
usage: test.py [-h] [-x HEIGHT] [-l LENGTH] [-b BREADTH] [--stop]
test.py: error: argument -l/--length: invalid int value: 'q'


Option with sys.argv

Typically the command line interface is used as follows (no input):


test.py -x 1 -l 2 -b 3

You can use sys.argv to get a list of command line arguments.

sys.argv

The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.


import argparse
import sys

# parser code here

# enable -h
args = parser.parse_args()

print(sys.argv)


if len(sys.argv) == 1:
    parser.error('First, set the height of the box.')
else:
    # throws an error if the arguments are out of order
    if sys.argv[1] not in ['-x', '--height']:
        parser.error('First, set the height of the box.')
    else:
        # do something
        print(args)

Output:


>test.py -l 7 -b 4 -x 3
['test.py', '-l', '7', '-b', '4', '-x', '3']
usage: test.py [-h] [-x HEIGHT] [-l LENGTH] [-b BREADTH] [--stop]
test.py: error: First, set the height of the box.


Important

It doesn't matter what order the arguments are in, their values are available through args.argumentname

height = args.height

length = args.length

breadth = args.breadth


import argparse


# parser code here

# Namespace object
args = parser.parse_args()

if args.height is None: # not set
    parser.error('Set the height of the box.')
else:
    # do something
    print(args.height + 1)

8349697
  • 415
  • 1
  • 6
  • 11