In all my scripts I use the standard flags --help and --version, however I cannot seem to figure out how to make a --version with parser.add_argument(..., required=True).
import sys, os, argparse
parser = argparse.ArgumentParser(description='How to get --version to work?')
parser.add_argument('--version', action='store_true',
help='print version information')
parser.add_argument('-H', '--hostname', dest='hostname', required=True,
help='Host name, IP Address')
parser.add_argument('-d', '--database', dest='database', required=True,
help='Check database with indicated name')
parser.add_argument('-u', '--username', dest='username', required=True,
help='connect using the indicated username')
parser.add_argument('-p', '--password', dest='password', required=True,
help='use the password to authenticate the connection')
args = parser.parse_args()
if args.version == True:
print 'Version information here'
$ ./arg.py --version
usage: arg.py [-h] [--version] -H HOSTNAME -d DATABASE -u USERNAME -p PASSWORD
arg.py: error: argument -H/--hostname is required
Yes, I want --hostname and others required, but I always want --version to work appropriately like --help (and -h).
$ ./arg.py --help
usage: arg.py [-h] [--version] -H HOSTNAME -d DATABASE -u USERNAME -p PASSWORD
How to get --version to work?
optional arguments:
-h, --help show this help message and exit
--version print version information
-H HOSTNAME, --hostname HOSTNAME
Host name, IP Address
-d DATABASE, --database DATABASE
Check database with indicated name
-u USERNAME, --username USERNAME
connect using the indicated username
-p PASSWORD, --password PASSWORD
use the password to authenticate the connection
Any help on getting --version to work?
There is a special version action keyword argument to add_argument (As documented here: argparse#action).
Try this (copied from working code):
parser.add_argument('-V', '--version',
action='version',
version='%(prog)s (version 0.1)')
Related
I try to use python for get VM name on VMware (vSphere) when I execute this python script:
https://github.com/vmware/pyvmomi-community-samples/blob/master/samples/get_vm_names.py
I have this message :
python3 test2.py --host ip_of_vmware
usage: test2.py [-h] -s HOST [-o PORT] -u USER [-p PASSWORD] [-S]
test2.py: error: the following arguments are required: -u/--user
I don't know how to execute this script.
I think this line which used to put in parameter:
si = SmartConnectNoSSL(host=args.host,
user=args.user,
pwd=args.password,
port=int(args.port))
atexit.register(Disconnect, si)
I want to know how to execute this script.
The arguments required for the program are built by setup_args function in that program which in turn appears to be constructed by this line:
parser = cli.build_arg_parser()
This is in a package I don't have so I can't see what it is doing.
Nevertheless the help message, without explicitly stating which arguments are mandatory, is hinting in that general direction. I believe the arguments in [ ] are optional and everything else is required, so you need at least -s HOST and -u USER
python3 test2.py -s HOST -u USER
or
python3 test2.py --host HOST --user USER
If you read message carefully it already tells how to use.
usage: test2.py [-h] -s HOST [-o PORT] -u USER [-p PASSWORD] [-S]
You need to pass all required arguments to run script successfully. Arguments given in [] means optional.
[-h] is to show the help message:
$ python get_vm_names.py -h
usage: get_vm_names.py [-h] -s HOST [-o PORT] -u USER [-p PASSWORD] [-nossl]
Arguments for talking to vCenter
options:
-h, --help show this help message and exit
standard arguments:
-s HOST, --host HOST vSphere service address to connect to
-o PORT, --port PORT Port to connect on
-u USER, --user USER User name to use when connecting to host
-p PASSWORD, --password PASSWORD
Password to use when connecting to host
-nossl, --disable-ssl-verification
Disable ssl host certificate verification
Look at the standard arguments in above message.
To run the script pass the arguments like this:
$ python get_vm_names.py -s <vSphere Server IP> -u <username> -p <Password>
or
$ python get_vm_names.py --host <vSphere Server IP> --user <username> --password <Password>
vSphere server IP, username and password are the same value which you use to connect to vSphere manually.
I need to ssh into a machine via a bastion. Therefore the command is rather very long for this:
ssh -i <pemfile location> -A -o 'proxycommand ssh -i <pemfile location> ec2-user#<bastion ip address> -W %h:%p' hadoop#<machine ip>
This command is rather very long. So I tried to write a python script which takes ip addresses and pemfile location as inputs and does ssh.
#!/usr/local/bin/python3
import argparse
import subprocess
import os
import sys
import errno
parser = argparse.ArgumentParser(description="Tool to ssh into EMR via a bastion host")
parser.add_argument('master', type=str, help='IP Address of the EMR master-node')
parser.add_argument('bastion', type=str, help='IP Address of bastion EC2 instance')
parser.add_argument('pemfile', type=str, help='Path to the pemfile')
args = parser.parse_args()
cmd_list = ["ssh", "-i", args.pemfile, "-A", "-o", "'proxycommand ssh -i {} ec2-user#{} -W %h:%p'".format(args.pemfile, args.bastion), "hadoop#{}".format(args.master)]
command = ""
for w in cmd_list:
command = command + " " + w
print("")
print("Executing command : ", command)
print("")
subprocess.call(cmd_list)
I get the following error when I run this script :
command-line: line 0: Bad configuration option: 'proxycommand
But I am able to run the exact command via bash.
Why is the ssh from python script failing then?
You are making the (common) mistake of mixing syntactic quotes with literal quotes. At the command line, the shell removes any quotes before passing the string to the command you are running; you should simply do the same.
cmd_list = ["ssh", "-i", args.pemfile, "-A",
"-o", "proxycommand ssh -i {} ec2-user#{} -W %h:%p".format(
args.pemfile, args.bastion), "hadoop#{}".format(args.master)]
See also When to wrap quotes around a shell variable? for a discussion of how quoting works in the shell, and perhaps Actual meaning of 'shell=True' in subprocess as a starting point for the Python side.
However, scripting interactive SSH sessions is going to be brittle; I recommend you look into a proper Python library like Paramiko for this sort of thing.
I am using argparse with subparsers to do different actions. Each action has slightly different arguments.
I have set it up as the documentations instructs, with one action in subparser (parser_2) and the other subparser (parser_3) when i do help for usage of each it says the correct parameters
This is for cdf:
positional arguments:
repo name the repo to perform tasks on
optional arguments:
-h, --help show this help message and exit
--state {open,closed}
Print issues in a repository having status of
all(default), open, or closed
this is for clsiss:
usage: subparsprob.py clsiss [-h] repo issnums [issnums ...]
positional arguments:
repo name the repo to perform tasks on
issnums put the issue number(s) separated by blank
optional arguments:
-h, --help show this help message and exit
however when i actually run the commands i get usage errors:
for clsiss executing from command line:
PS C:\xxx> python subparsprob.py clsiss repo 1
usage: subparsprob.py clsiss [-h] repo issnums [issnums ...]
subparsprob.py clsiss: error: argument issnums: invalid int value: 'repo'
for cdf (executing from command line):
PS C:\xxx> python subparsprob.py cdf repo
usage: subparsprob.py clsiss [-h] repo issnums [issnums ...]
subparsprob.py clsiss: error: argument issnums: invalid int value: 'repo'
please help, I am using the correct arguments and number of argument but cannot figure out why the usage is wrong when i actually try to run it
i am still getting the same error , here is the entire code, I cannot figure it out. Please help
#!/usr/bin/python3
import argparse
import sys
import os
argv = sys.argv[1:]
# from issueGithub import IssueGithub, Taskname
def main():
parser=argparse.ArgumentParser(description='Invoke various github
actions')
subparsers = parser.add_subparsers(help='sub-commands for Github
options',dest='action_name')
parser_2 =subparsers.add_parser('clsiss',help='close issues')
parser_2.add_argument('repo',type=str,help="name the repo to perform
tasks
on")
parser_2.add_argument('issnums',type=int,nargs='+',help="put the issue
number(s) separated by blank")
parser_3 = subparsers.add_parser('cdf',help='create default
tasks/issues')
parser_3.add_argument('repo',type=str,help="name the repo to perform
tasks
on")
parser_3.add_argument('--state',choices=['open','closed'], default='all',
help='Print issues in a repository
args = parser.parse_args()
args2 = parser_2.parse_args()
args3 = parser_3.parse_args()
print("Args are")
print(args)
print(args2)
print(args3)
if __name__ =="__main__":
main()
With a copy-n-paste of your code:
1301:~/mypy$ python3 stack58684096.py -h
usage: stack58684096.py [-h] {clsiss,cdf} ...
Invoke various actions
positional arguments:
{clsiss,cdf} sub-commands for options
clsiss close issues
cdf create default tasks/issues
optional arguments:
-h, --help show this help message and exit
I don't get your errors:
1302:~/mypy$ python3 stack58684096.py clsiss repo 1
Namespace(action_name='clsiss', issnums=[1], repo='repo')
1302:~/mypy$ python3 stack58684096.py cdf repo
Namespace(action_name='cdf', repo='repo', state='all')
1302:~/mypy$ python3 stack58684096.py clsiss -h
usage: stack58684096.py clsiss [-h] repo issnums [issnums ...]
positional arguments:
repo name the repo to perform tasks on
issnums put the issue number(s) separated by blank
optional arguments:
-h, --help show this help message and exit
Your errors - sort of:
1302:~/mypy$ python3 stack58684096.py clsiss repo
usage: stack58684096.py clsiss [-h] repo issnums [issnums ...]
stack58684096.py clsiss: error: the following arguments are required: issnums
1304:~/mypy$ python3 stack58684096.py clsiss repo repo
usage: stack58684096.py clsiss [-h] repo issnums [issnums ...]
stack58684096.py clsiss: error: argument issnums: invalid int value: 'repo'
Hi I'm using ArgParse to handle my arguments. I would like the code to work like this
# Main function
$ myApp -i INPUT -o OUTPUT -s STUFF
# Configure function
$ myApp config -a conf1 -b conf2
import argparse
from argparse import RawTextHelpFormatter
parser = argparse.ArgumentParser(description='myApp',formatter_class=RawTextHelpFormatter)
parser.add_argument('-i',help='input',required=True)
parser.add_argument('-o',help='output',required=True)
parser.add_argument('-s',help='stuff',default=None,required=False)
args = parser.parse_args()
subp = parser.add_subparsers()
conf_parser = subp.add_parser('config', help='configure')
conf_parser.add_argument('-a',help='a config file',default=None,required=False)
conf_parser.add_argument('-b',help='b config file',default=None,required=False)
conf_args = conf_arser.parse_args()
Here's the output
python sandbox/test1.py --help
usage: test1.py [-h] -i I -o O [-s S]
myApp
optional arguments:
-h, --help show this help message and exit
-i I input
-o O output
-s S stuff
I'm not getting the config args to show. I'm not sure what I'm doing wrong here.
Thanks!
Solved it
import argparse
from argparse import RawTextHelpFormatter
parser = argparse.ArgumentParser(description='myApp',formatter_class=RawTextHelpFormatter)
parser.add_argument('-i',help='input',required=True)
parser.add_argument('-o',help='output',required=True)
parser.add_argument('-s',help='stuff',default=None,required=False)
subp = parser.add_subparsers(help='configure')
conf_parser = subp.add_parser('config')
conf_parser.add_argument('-a',help='a config file',default=None,required=False)
conf_parser.add_argument('-b',help='b config file',default=None,required=False)
args = parser.parse_args()
python sandbox/test1.py --help
usage: test1.py [-h] -i I -o O [-s S] {config} ...
myApp
positional arguments:
{config} configure
optional arguments:
-h, --help show this help message and exit
-i I input
-o O output
-s S stuff
python sandbox/test1.py config --help
usage: test1.py config [-h] [-a A] [-b B]
optional arguments:
-h, --help show this help message and exit
-a A a config file
-b B b config file
I am trying to have a required mutually exclusive group with one required parameter. Below is the code which I have put
#!/usr/bin/python
import argparse
import sys
# Check for the option provided as part of arguments
def parseArgv():
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", choices=[1,2,3,4],
help = "Increase verbosity")
group.add_argument("-q", "--quiet", action="store_true", help = "Run quietly")
name = parser.add_mutually_exclusive_group(required=True)
name.add_argument("-n", "--name", help = "Name of the virtual machine")
name.add_argument("-t", "--template", help = "Name of the template to use \
for creating vm. If path is not provided then it will be looked \
under template directory.")
parser.add_argument("-s", "--save", help = "Save the machine template. If \
path is not provided then it will be saved under template directory.");
#parser.add_argument("-k", "--kick_start", required = True, help = "Name of the \
# kick start file. If path is not provided then it will be look into http \
# directory.")
if len(sys.argv) == 1:
parser.print_help()
args = parser.parse_args()
if __name__ == '__main__':
parseArgv()
Now the output of this program as follow
$ python test.py
usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE]
optional arguments:
-h, --help show this help message and exit
-v {1,2,3,4}, --verbose {1,2,3,4}
Increase verbosity
-q, --quiet Run quietly
-n NAME, --name NAME Name of the virtual machine
-t TEMPLATE, --template TEMPLATE
Name of the template to use for creating vm. If path
is not provided then it will be looked under template
directory.
-s SAVE, --save SAVE Save the machine template. If path is not provided
then it will be saved under template directory.
usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE]
test.py: error: one of the arguments -n/--name -t/--template is required
But if I un-comment the from line 20 - 22 then the output change as below
$ python test.py
usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE] -k
KICK_START
optional arguments:
-h, --help show this help message and exit
-v {1,2,3,4}, --verbose {1,2,3,4}
Increase verbosity
-q, --quiet Run quietly
-n NAME, --name NAME Name of the virtual machine
-t TEMPLATE, --template TEMPLATE
Name of the template to use for creating vm. If path
is not provided then it will be looked under template
directory.
-s SAVE, --save SAVE Save the machine template. If path is not provided
then it will be saved under template directory.
-k KICK_START, --kick_start KICK_START
Name of the kick start file. If path is not provided
then it will be look into http directory.
usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE] -k
KICK_START
test.py: error: argument -k/--kick_start is required
But I want that either -n / -t along with -k become mandatory. How to achieve the same.
You have already achieved it! Argparse only prints the first error it finds, so while it may look like it's only checking -k, it actually recuires -n/-t too. You can see this by actually giving it the -k argument.
If you provide the -k argument, the error message will change from test.py: error: argument -k/--kick_start is required to test.py: error: one of the arguments -n/--name -t/--template is required.