I have a setup like this. What I want to do is to send a constant value if only the -e/--exp are sent, and if -p/--plot are sent then it should only do the plotting. So a default value will not work, as it then will print 'do everything'.
def run(args):
if args.exp:
if 'p' in args.exp:
print('p')
if 'q' in args.exp:
print('q')
if 't' in args.exp:
print('t')
else:
print('do everything')
if args.plot:
if 'p' in args.plot:
print('plot p')
if 'q' in args.plot:
print('plot q')
if 't' in args.plot:
print('plot t')
else:
print('plot everything')
if __name__=="__main__":
parser = argparse.ArgumentParser(
prog="test.py")
parser.add_argument('-e', '--exp', nargs='*',
help='pass p, q , t or nothing')
parser.add_argument('-p', '--plot', nargs='*',
help='pass p, q , t or nothing')
args = parser.parse_args()
run(args=args)
So basically what I want is to have it like this.
if __name__=="__main__":
parser = argparse.ArgumentParser(
prog="test.py")
parser.add_argument('-e', '--exp', nargs='*', const='a'
help='pass p, q , t or nothing')
so that if I run python test.py -e it should print 'do everything'
And if i run python test.py -p it should print 'plot everything'
if run python test.py -e p it should print 'p'
and python test.py -e p q it should print 'p' and 'q'
Is this possible without writing a custom action as nargs='*' does not support const value
Basically you just need to use choices argument. Also I'd suggest you to use mutually exclusive group to avoid both -e and -p modes.
from argparse import ArgumentParser
parser = ArgumentParser()
mode = parser.add_mutually_exclusive_group(required=True)
mode.add_argument("-e", "--exp", nargs="*", choices=("p", "q", "t"))
mode.add_argument("-p", "--plot", nargs="*", choices=("p", "q", "t"))
args = parser.parse_args()
if args.exp is None:
if args.plot:
print(*args.plot)
else:
print("plot everything")
else:
if args.exp:
print(*args.exp)
else:
print("do everything")
Related
I wrote cmd line interface to perform calculation on a number. If I enter using powershell the command:
python .\regex1.py *x 5 *y 6 *o mul
it prints:
In calc args
Something went wrong
However if i comment out Nargs it gives the expected results.
entered thiscommand: python .\regex1.py *x 5 *y 6 *o mul
Got :mul
30.0
Why is it so, why is Nargs creating this problem and how to solve it while keeping Nargs in our code? The code is below:
import argparse
import sys
def calc(args):
print("In calc args")
if str(args.o) == 'add':
return args.x + args.y
elif str(args.o) == 'mul':
return args.x * args.y
elif str(args.o) == 'sub':
return args.x - args.y
elif str(args.o) == 'div':
return args.x / args.y
else:
return "Something went wrong"
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog= "utility Calculator",
usage= "To perform calculation on an integer",
description="Thsi is arguments help",
epilog="Hope your problem is resolved, if not contact me",
prefix_chars="*",
argument_default= 1.0,
add_help= True,
allow_abbrev= True
)
parser.add_argument('*x',
type=float,
action="store",
nargs=1,
help="Enter first number. This is a utility for calculation. Please contact me",
metavar= " First Number"
)
parser.add_argument('*y',
type=float,
action="store",
nargs=1,
help="Enter Second number. This is a utility for calculation. Please contact me",
metavar= " Second Number"
)
parser.add_argument('*o',
type=str,
# action="store"
nargs=1,
default= "add",
help="Enter the operand."
"*mul for multiplication"
"*add for addition"
"*div for division"
"*sub for subtraction",
metavar= " Operand"
)
args = parser.parse_args()
print(str(args.o), args.x, args.y)
sys.stdout.write(str(calc(args)))
nargs serves a different purpose and I'm not sure why you are trying to use it here since your arguments contain only one value.
When nargs=1 your argument is actually a list of that single argument. If you remove the nargs=1 you get the argument itself. And looking at your code, all if statements fail and that's why you get Something went wrong.
Referencing the documentation where you can learn more about nargs:
N (an integer). N arguments from the command line will be gathered together into a list. For example:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2)
>>> parser.add_argument('bar', nargs=1)
>>> parser.parse_args('c --foo a b'.split())
Namespace(bar=['c'], foo=['a', 'b'])
Note that nargs=1 produces a list of one item. This is different from the default, in which the item is produced by itself.
I have the following Python code that has 1 command line optional parameter (c) that has an argument and 2 options (a and b) that do not have an argument:
import sys, getopt
def main(argv):
inputfile = ''
outputfile = ''
try:
opts, args = getopt.getopt(argv,"abc:",["csvfile="])
except getopt.GetoptError:
print 'Error in usage - a does not require an argument'
sys.exit(2)
for opt, arg in opts:
print "Raw input is: {}" .format(opt)
if opt in ("-c", "--csvfile"):
outputfile = arg
print 'Output file is {}' .format(outputfile)
elif opt == '-a':
print 'Alpha'
elif opt == '-b':
print 'Beta'
print 'User choice is {}' .format(opt.lstrip('-'))
if __name__ == "__main__":
main(sys.argv[1:])
When I enter python readwritestore.py -a I get:
Raw input is: -a
Alpha
User choice is a
This is what I was hoping for if the commandline argument is -a. However, if I enter python readwritestore.py -a csvfile_name, then I get:
Raw input is: -a
Alpha
User choice is a
This is not what I intended for. In this function, c is the only option that rquires an argument. If I enter a with an argument,
the code should give the error message that I set up
Error in usage - a does not require an argument
This does not happen for a or b. It is allowing the argument to be entered without raising an error.
If the options that do not require an argument are entered with an argument, then I would like it to raise an error. python readwritestore.py -a text
and python readwritestore.py -b text should raise the error Error in usage - a does not require an argument.
Is there a way to specify this? Is getopt() the correct way to do this?
Additional Information:
I only want python readwritestore.py -c text to work with the argument. For the other 2 options, a and b, the code should raise the error.
checking the size of sys.argv (the list of argument supplied when calling the script) can help you checking that :
import sys
import getopt
def main(argv):
inputfile = ''
outputfile = ''
opts, args = getopt.getopt(argv, "abc:", ["csvfile="])
for opt, arg in opts:
print "Raw input is:", opt
if opt in ("-c", "--csvfile"):
outputfile = arg
print 'Output file is ', outputfile
elif opt == '-a':
if len(sys.argv)=2:
print 'Alpha'
else:
print "incorect number of argument"
elif opt == '-b':
if len(sys.argv)=2:
print 'Beta'
else:
print "incorect number of argument"
print 'User choice is ', opt
if __name__ == "__main__":
main(sys.argv[1:])
I know it's not what you asked (argparse) but here is how you could do it with argparse :
from argparse import *
def main():
parser = ArgumentParser()
parser.add_argument('-c', '--csvfile', help='do smth with cvsfile')
parser.add_argument(
'-a', '--Alpha', help='Alpha', action='store_true')
parser.add_argument(
'-b', '--Beta', help='beta smth', action='store_true')
if args.csvfile:
print 'Output file is {}' .format(args.csvfile)
if args.Alpha:
print 'Alpha'
if args.Beta:
print 'Beta'
if __name__ == "__main__":
main()
It will raise an error is to many argument are supplied. (also python readwritestore.py -h will display the help just like man in unix)
I want to do something like this in my python code
python my_prog.py -inp 3 -inp2 4
and be able to use inp and inp2 as inputs in my python program. How can I do it?
You're looking for the argparse module.
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('input1', metavar='a', type=int, help='an input for foo')
parser.add_argument('input2', metavar='b', type=int, help='an input for bar')
args = parser.parse_args()
print(args.input1 + args.input2)
You can use getopt for parsing input arguments.
Example from the docu:
import getopt, sys
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
except getopt.GetoptError as err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
output = None
verbose = False
for o, a in opts:
if o == "-v":
verbose = True
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-o", "--output"):
output = a
else:
assert False, "unhandled option"
# ...
if __name__ == "__main__":
main()
Im trying to send some command line arguments to a program I've written. I adapted some code I found in a tutorial. However, only the last of the arguments I am sending seam to be getting through. For example, if I type the following in:
python test.py -m A
Nothing happens, however, if I type in:
python test.py -s A
the final argument in the list it seams to work... (code attached below)
import sys, getopt
def main(argv):
mina = ""
capsize= ""
matchcharge= ""
steps= ""
try:
opts, args = getopt.getopt(argv,"m:cs:mc:s:",["min=","capsize=","matchcharge=","steps="])
except getopt.GetoptError:
print("argument not recognised")
sys.exit(2)
for opt, arg in opts:
if opt == ("-m", "--min"):
mina = arg
print("1")
elif opt in ("-cs", "--capsize"):
capsize = arg
print("2")
elif opt in ("-mc", "--matchcharge"):
matchcharge = arg
print("3")
elif opt in ("-s", "--steps"):
steps = arg
print("4")
print("mina " + str(min))
print("capsize" + str(capsize))
print("matchcharge" + str(matchcharge))
print("steps " + str(steps))
if __name__ == "__main__":
main(sys.argv[1:])
In your code you have
if opt == ("-m", "--min"):
which should be
if opt in ("-m", "--min"):
Since you had that right on all the other places, I guess this was just forgotten there.
so I wrote a program and I want to pass it either a filename and an integer or just an integer. Whats the best way to determine which argument is the integer? This is what I have:
import sys
if len(sys.argv) > 1):
for e in sys.argv:
try:
bio = map(e, int)
except:
pass
thanks in advance
You could check whether or not the argument is an integer with the string isdigit() method:
import sys
if len(sys.argv) > 1:
for e in sys.argv:
if e.isdigit():
# all characters in e are digits and there is at least one character in e
else:
# it is possibly your filename argument
But, I should encourage you to give a chance to the argparse library: http://docs.python.org/dev/library/argparse.html
import argparse
parser = argparse.ArgumentParser(description = 'A simple description')
parser.add_argument('-f', action = 'store', dest = 'filename', required = False)
parser.add_argument('-n', action = 'store', dest = 'n', required = True, type=int)
arguments = parser.parse_args()
print arguments.n
print arguments.filename
def isint(val):
try:
int(val)
return True
except:
return False
int_args = filter(isint,sys.argv)
not_int_args = set(sys.argv) - set(int_args)
if len(sys.argv) == 1: #user passed in only one argument. It must be an integer.
bio = int(sys.argv[0])
elif len(sys.argv) == 2: #user passed in two arguments: filename and integer.
filename = sys.argv[0]
bio = int(sys.argv[1])
else: #user didn't pass in the right number of arguments
raise Exception("Expected one or two arguments")