1

I am trying to use the argparse library with python2 but it always gives error:

Code:

parent_parser = argparse.ArgumentParser()
sub_parsers = parent_parser.add_subparsers(title = "actions")

parser_create = sub_parsers.add_parser("create", parents = [parent_parser], add_help = False, description = "Create new Customer account.", help = "create")
parser_create.add_argument('-p', '--password', help = 'User Password', required = True)
parser_create.add_argument('-n', '--fullname', nargs = 2, help = 'User Full Name', required = True)
parser_create.add_argument('-e', '--email', required = True, help = "User Email address")

parser_deactivate = sub_parsers.add_parser("deactivate", parents = [parent_parser], add_help = False, description = "Deactivate existing customer account.", help = "deactivate.")
parser_deactivate.add_argument('-e','--email', required = True, help = "User Email address")
args = parent_parser.parse_args()

Output:

[root@localhost ~]# python2 create-user.py deactivate -e o@x.com

usage: create-user.py deactivate [-h] -e EMAIL {create,deactivate} ...
create-user.py deactivate: error: too few arguments

Same error appears when using the create instead of deactivate.

also it works perfectly fine with python3.x.

Omar Abdelrazik
  • 683
  • 2
  • 9
  • 30
  • 2
    Why are you adding `parent_parser` as a parent to the subparsers? Just remove that. – chepner Jun 23 '20 at 12:38
  • What output does `python2 create-user.py -h` give? The generated online help should show what argparse expects – Useless Jun 23 '20 at 12:40
  • @Useless usage: test.py create [-h] -p PASSWORD -f FULLNAME FULLNAME -e EMAIL {create,deactivate} ... optional arguments: -h, --help show this help message and exit -p PASSWORD, --password PASSWORD User Password -f FULLNAME FULLNAME, --fullname FULLNAME FULLNAME User Full Name -e EMAIL, --email EMAIL User Email address actions: {create,deactivate} create To create new customer accounts deactivate To deactivate new customer accounts. – Omar Abdelrazik Jun 23 '20 at 13:54
  • In py2 subparsers are required, in py3 they are not (by default that is). So the recursive use of the parent_parser doesn't give problems in py3, but does make py2 impossible. Drop the `parents` bit. – hpaulj Jun 23 '20 at 14:50
  • That information should be in the question, where it would be legible. – Useless Jun 23 '20 at 15:50
  • @hpaulj that actually worked. Thank you. But I need to have different options depending on whether the user chooses 'create' or 'deactivate'. Is there a workaround for that? – Omar Abdelrazik Jun 23 '20 at 19:50
  • Each of the subparsers has its own set of defined arguments. You already do that with '-p' and '-n' for one. – hpaulj Jun 23 '20 at 19:53

1 Answers1

0

parents is used to "inherit" arguments from one or more parsers without repeating their definition across multiple parsers.

Your subparsers don't need to do that. You are effectively saying that after you use the subcommand deactivate, you need to again specifying either create or deactivate, leading to an infinite loop.

Just omit the parents argument to the subparsers.

import argparse


parser = argparse.ArgumentParser()
sub_parsers = parser.add_subparsers(title="actions")

parser_create = sub_parsers.add_parser("create", 
                                       description="Create new Customer account.")
parser_create.add_argument('-p', '--password',
                           help='User Password', required=True)
parser_create.add_argument('-n', '--fullname', nargs=2,
                           help='User Full Name', required=True)
parser_create.add_argument('-e', '--email', required=True,
                           help="User Email address")

parser_deactivate = sub_parsers.add_parser("deactivate",
                                           description="Deactivate existing customer account.")
parser_deactivate.add_argument('-e','--email', required=True,
                               help="User Email address")

args = parser.parse_args()

A sample run:

$ python2 create-user.py deactivate -e o@x.com
Namespace(email='o@x.com')

One way you might use a parent parser is to inherit --email from a single parser.

parser = argparse.ArgumentParser()

email_parser = argparse.ArgumentParser(add_help=False)
email_parser.add_argument("-e", "--email", required=True,
                          help="User Email address")

sub_parsers = parser.add_subparsers(title="actions")

parser_create = sub_parsers.add_parser("create",
                                       description="Create new Customer account.",
                                       parents=[email_parser])
parser_create.add_argument('-p', '--password',
                           help='User Password', required=True)
parser_create.add_argument('-n', '--fullname', nargs=2,
                           help='User Full Name', required=True)

parser_deactivate = sub_parsers.add_parser("deactivate",
                                           description="Deactivate existing customer account.",
                                           parents=[email_parser])

args = parser.parse_args()
chepner
  • 497,756
  • 71
  • 530
  • 681