Python argparse module usage - python

I have a program which is called like this:
program.py add|remove|show
The problem here is that depending on the add/remove/show command it takes a variable number of arguments, just like this:
program.py add "a string" "another string"
program.py remove "a string"
program.py show
So, 'add' command would take 2 string arguments, while 'remove' command would take 1 only argument and 'show' command wouldn't take any argument.
I know how to make a basic argument parser using the module argparse, but I don't have much experience with it, so I started from this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("command", choices=["add", "remove", "show"])
But I don't know how to continue and how to implement this functionality depending on the command. Thanks in advance.

You're looking for argparse's subparsers...
parser = argparse.ArgumentParser(prog='PROG')
subparsers = parser.add_subparsers(help='sub-command help')
# create the parser for the "add" command
parser_add = subparsers.add_parser('add', help='add help')
# [example] add an argument to a specific subparser
parser_add.add_argument('bar', type=int, help='bar help')
# create the parser for the "remove" command
parser_remove = subparsers.add_parser('remove', help='remove help')
# create the parser for the "show" command
parser_show = subparsers.add_parser('show', help='show help')
This example code is stolen with very little modification from the language reference documentation.

Related

python argparse separate 2 options of comamnds

I've read the documentation but still can't figure out how to achieve the following behavior:
1.likes. Give a specified number of likes to users in a tinder (in the future, this may contain more options, such as "gender", "frequency", "age", etc.)
2. Write a given text to a given number of people on tinder (in the future, there may also be more options).
There is my code:
parser = argparse.ArgumentParser(description='Badoo liker', epilog='Enjoy the program! :)')
# I also tried "add_mutually_exclusive_group" instead of "add_argument_group"
chat_args = parser.add_argument_group(title='chat_args')
chat_args.add_argument('-c', '--chat', help='chat help')
chat_args.add_argument('-t', '--text', help='text help')
chat_args.add_argument('-n', '--number', help='n help')
like_args = parser.add_argument_group(title='like_args')
like_args.add_argument('-l', '--like', help='like help')
like_args.add_argument('-n', '--number', help='n help')
args = parser.parse_args()
Usage:
$script.py chat --text 'Hello world' -n 20 # Var 1
$script.py liking -n 20 # Var 2
Obviously, I'm waiting for arguments either for a chat or either for liking
P.S. I'm getting an error because of -n common argument, but even if comment it it will not working as expecting
It's a little hard to tell what you understand and what has worked or not for you.
This is more of a comment, but long enough that I'll make it answer.
Are those usage lines samples of what you use when calling this script? What error(s) do you get?
Have you tried scipt.py -h to see the help?
I don't see a positional argument that would accept a string like "chat" or "liking". I suspect you want to use the subcommands mechanism, but get the basic argparse working.
I often suggest including a print(args) line to get a clear idea of what the parser has done. Though obviously you won't see that while argparse is raising errors.
Postpone the use of groups until you get the basics down. argument_group just groups arguments in the help display. mutually_exclusive_group is a parsing tool, that complains if you try to use more than one item in the group.
Eventually, I did it, the next code is (apparently) meets my question
# "metavar=''" -just hide redundant double --key KEY word
parser = argparse.ArgumentParser(description='Badoo liker', epilog='Enjoy the program! :)')
subparsers = parser.add_subparsers(help='')
parser_like = subparsers.add_parser('like', help='like help')
parser_like.add_argument('-n', '--number', metavar='', help='Set count of likes', default=49)
parser_like.add_argument('-f', '--frequency', metavar='', help='Set chance to like/dislike', default=70)
parser_chat = subparsers.add_parser('chat', help='chat help')
parser_chat.add_argument('-n', '--number', metavar='', help='number help', required=True)
parser_chat.add_argument('-t', '--text', metavar='', help='text help', required=True)
args = parser.parse_args()

How to print just the content of the help string of a specific argument of ArgParse

Is there a way to access the help strings for specific arguments of the argument parser library object?
I want to print the help string content if the option was present on the command line. Not the complete help text that Argument Parser can display via ArgumentParser.print_help .
So something along those lines:
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--do_x", help='the program will do X')
if do_x:
print(parser.<WHAT DO I HAVE TO PUT HERE?>('do_x')
And this is the required behavior
$program -d
the program will do X
There is parser._option_string_actions which is mapping between option strings (-d or --do_x) and Action objects. Action.help attribute holds the help string.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--do_x", action='store_true',
help='the program will do X')
args = parser.parse_args()
if args.do_x:
print(parser._option_string_actions['--do_x'].help)
# OR print(parser._option_string_actions['-d'].help)
parser._actions is a list of the Action objects. You can also grab object when creating the parser.
a=parser.add_argument(...)
...
If args.do_x:
print a.help
Play with argparse in an interactive session. Look at a from such an assignment.

Common positional arguments in different subparsers

I am trying to make a parser using argparse than can parse the following commands:
python prog.py update <DOMAIN> <ENVIRONMENT>
python prog.py pull <DOMAIN> <ENVIRONMENT>
python prog.py release <DOMAIN> <ENVIRONMENT>
As you can see, both update, pull and release take the same arguments <DOMAIN> and <ENVIRONMENT>.
All three of them are subparsers of the main parser.
I wrote the following:
import argparse
# create the top-level parser
parser = argparse.ArgumentParser(prog='PROG', add_help=False)
parser.add_argument('domain', type=str, help='domain help')
parser.add_argument('environment', type=str, help='environment help')
#subparsers
subparsers = parser.add_subparsers(help='sub-command help', parents=[parser])
parser_pull = subparsers.add_parser('pull', help='pull help')
parser_update = subparsers.add_parser('update', help='update help')
print parser_pull.parse_args(['pull', 'WEBAPPS', 'DEV'])
print parser.parse_args(['update', 'WEBAPPS', 'DEV'])
but it seems that domain and environment are expected BEFORE the subcommands update, pull and release, so it throws an error.
How can I make it required to accept those arguments after the subcommands, without duplicating code inside each subcommand ?
For the record, I use Python 2.7.
Go ahead and duplicate the code. A little cut and paste is not that much work.
Positional arguments have to be given in a certain order. And .add_subparsers creates one of those positionals (one that expects values like 'pull','update'. So the order of the subparse command, positionals defined for the main parser, and positionals for the subparsers matters.
There is a parents mechanism, which can save some typing. But I hesitate to recommend it because it can cause problems (previous SO questions demonstrate this). Simply biting the bullet and entering the positional arguments where they are expected is the surest approach.
Don't forget that you can create subparsers in a loop or with helper functions - saving one kind of typing for another.
For example, after creating the subparsers:
for p in parser_pull, parser_update:
p.add_argument('domain', type=str, help='domain help')
p.add_argument('environment', type=str, help='environment help')

Use argparse module in python to parse a single argument

I used the OptParse module a few years back, and it seemed so easy, but seeing the argparse module, it doesn't seem intuitive to use. Thus, I'd like some help.
I currently have (which isnt much yet):
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
I'd like to be able to issue a command like python myscript.py --char 20 . This value for char flag will always be an int.
If someone can please help, I'd greatly appreciate it! Thank you
This is how you add an argument, and retrieve it:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--char', type=int,
help='number of characters')
args = parser.parse_args()
char = args.char
You should check out the docs:
https://docs.python.org/3/library/argparse.html
And here's a tutorial:
https://docs.python.org/2/howto/argparse.html
you need to add an argument to the parser object, and optionally specify the parameter type to be int
# testargs.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--char', type=int)
args = parser.parse_args()
print(args.char)
if you execute this file with
python testargs.py --char 20
it should print 20 to the console

Python argparse conditional arguments

I am creating a program that requires conditional arguments using argparse. I would like to generate new arguments in my code depending on if a previous argument has been entered or not. Here is a basic example of how I would like my code to look
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-bowtie",action = "store_true",help="use to run bowtie")
args = parser.parse_args()
if args.bowtie:
parser.add_argument( add some new argument here )
args = parser.parse_args()
I've been doing a lot of stuff recently that's really similar to this. Look into subparsers:
parser = argparser.ArgumentParser
subparsers = parser.add_subparsers('-bowtie')
subparser = subparsers.add_parser()
subparser.add_argument('new argument')

Categories