How to switch default True to False on specifying and argument? - python

#!/usr/bin/env python
import optparse
p = optparse.OptionParser()
p.add_option("-o", action="store", dest="outfile")
p.add_option("-d", action="store_true", dest="debugflag")
p.set_defaults(debugflag=True)
opts,args = p.parse_args()
print opts, " ", args
print opts.outfile, opts.debugflag
Output:
$ ./optparseexample.py -o myfile -d
{'outfile': 'myfile', 'debugflag': True} []
myfile True
$ ./optparseexample.py -o myfile
{'outfile': 'myfile', 'debugflag': True} []
myfile True
Question:
How to I switch the default value for debugflag from True to False ?

You should use action=store_false then.
p.add_option("-d", action="store_false", dest="debugflag")
Please try to read the documentation before asking.

Related

Why can't I see the boolean value of my argparse variables in pdb?

I have the following code:
def main():
argParser = argparse.ArgumentParser(description = 'DESCRIPTION',epilog = 'Please see README.MD for guidance on how to use this script')
argParser.add_argument('-i', '--inFile', action='store',type=str, help = 'Input config file')
argParser.add_argument('-o', '--outFile', action = 'store', default = sys.stdout, type = argparse.FileType('w'), help = 'Output VCD File')
# generate_config_group = argParser.add_mutually_exclusive_group()
_ = argParser.add_argument('-g','--generate_config',action='store_true')
args = argParser.parse_args()
print(args,"THESE ARE MY ARGS")
print(args.generate_config,"This is the value of generate_config")
pdb.set_trace()
Now I run it
$ python src\dspwave8b10b2vcd.py -g
Namespace(generate_config=True, inFile=None, outFile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>) THESE ARE MY ARGS
True This is the value of generate_config
> c:\main\femtotest\tools\dspwave8b10b2vcd\src\dspwave8b10b2vcd.py(153)main()
-> if args.generate_config:
(Pdb) args
(Pdb) args.generate_config
(Pdb) args.g
(Pdb) args.g == True
Why is it that its prints out my arguments with generate_config being True for instance. Yet when I try and evaluate the value in pdb, it returns nothing.
As I had to piece the solution together from the comments, I will summarize it here:
args is a keyword for pdb. Similar to when you name a variable c or s or q you won't be able to access it as usual by writing its name in the command prompt. you can access a variable named like that by prepending p.
So p args.g would work to show the value of args.g. But typing args.g in the pdb console breaks.

python argparse subparser assign value to variable

i want to assign the subparser values to a variable like 'rport' so when the user call argument with value like
python example.py -sock connectmode -rport 10000
the rport variable take the 10000 int value but that code return error in the last line in 'rport = '
AttributeError: 'Namespace' object has no attribute 'rport'
notes : the subparsers is for a function is called 'socketfunc'
i wanted them to be a subargs for '-sock' argument
when i execute : 'python example.py -sock connectmode -h
return the secondary_parser args
[!]another note : the rport and rhost variables is global to make their values available to all functions
any help ! and thanks.
the code is :
import argparse
import socket
parser = argparse.ArgumentParser(epilog='\tExample: \r\npython ' + sys.argv[0])
parser.error = parser_error
parser._optionals.title = "OPTIONS"
subparsers = parser.add_subparsers(help='Specify secondary options')
global rport , rhost
secondary_parser = subparsers.add_parser('connectmode', help='sock argument connectmode')
listenmode_parser = subparsers.add_parser('listenmode',help='sock argument listenmode')
parser.add_argument('-sock','--socket',help="tcp socket functions [!] support only ipv4 for now",action="store_true")
secondary_parser.add_argument('-rport','--remoteport',help="destination port to connect to",required=True,action='store')
secondary_parser.add_argument("-rhost",'--destination',help="destination host ip addr",required=True,action='store')
secondary_parser.set_defaults(func=socketfunc)
listenmode_parser.set_defaults(func=socketfunc)
args = parser.parse_args()
rport = args.rport
import sys
def getcmdlineargv(argv):
"""Function to get values from cmd line and converted into dictionary"""
opts = {} # dictionary to store key-value pairs.
while argv: # until arguments left to parse...
if argv[0][0] == '-': # Found a "-name value" pair.
opts[argv[0]] = argv[1] # Add key and value to the dictionary.
argv = argv[1:] # Reduce the argument list by copying it starting from index 1.
return opts
argvDict = getcmdlineargv(sys.argv)
print(argvDict)
>>> python filename.py -sock connectmode -rport 10000
>>> {'-sock': 'connectmode', '-rport': '10000'}
Using argument parser:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-sock", type=str, help='')
parser.add_argument("-rport", type=int, help='')
parsarg = vars(parser.parse_args())
print(parsarg.get('rport'))
>>> python filename.py -sock connectmode -rport 10000
>>> 10000
Hope this will solve your problem to get command line argument.
hello guys the soloution is that replace
rport = args.rport with rport=args.remoteport the short arg doesnt conain the value but should specify the long arg name
thanks for all.
It's hard to figure out what you want. The description is poorly formated and rambling. But I'll try to explain what your code is doing.
Simplified a bit:
import argparse
parser = argparse.ArgumentParser()
parser._optionals.title = "OPTIONS"
subparsers = parser.add_subparsers(help='Specify secondary options')
global rport , rhost
secondary_parser = subparsers.add_parser('connectmode', help='sock argument connectmode')
listenmode_parser = subparsers.add_parser('listenmode',help='sock argument listenmode')
parser.add_argument('-sock','--socket',action="store_true")
secondary_parser.add_argument('-rport','--remoteport',required=True)
secondary_parser.add_argument("-rhost",'--destination',required=True)
secondary_parser.set_defaults(func='secondary')
listenmode_parser.set_defaults(func='listen')
args = parser.parse_args()
print(args)
With the connectmode values:
1027:~/mypy$ python3 stack48264081.py -sock connectmode -rport 10000
usage: stack48264081.py connectmode [-h] -rport REMOTEPORT -rhost DESTINATION
stack48264081.py connectmode: error: the following arguments are required: -rhost/--destination
Why? Because you defined -rhost as a required argument for the connectmode subparser. If I provide both:
1031:~/mypy$ python3 stack48264081.py -sock connectmode -rport 10000 -rhost foo
Namespace(destination='foo', func='secondary', remoteport='10000', socket=True)
In this case args.remoteport would work. args.rport would not, because the dest is taken from the long name, --, not the short one.
1034:~/mypy$ python3 stack48264081.py listenmode
Namespace(func='listen', socket=False)
args.remoteport would not work here because that argument is not defined for this subparser.
-sock is a simple True/False argument, and has nothing to do with the subparsers.

argparse: Default value for nargs='*'?

I tried to use this statement :
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False, const=True)
args = parser.parse_args()
print(args.music)
But got this error:
`builtins.ValueError: nargs must be '?' to supply const`
what i want to do is :
if -m is in args list but whithout any value, args.music will give me True
if -m is in args list and have 'N' values, args.music will give me a list of all values
if -m is not in args list, args,music will return False
the second and lastOne worked but, when i try to use const i got an error
You could use a custom action:
import argparse
class EmptyIsTrue(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if len(values) == 0:
values = True
setattr(namespace, self.dest, values)
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False, action=EmptyIsTrue)
print(parser.parse_args([]))
# Namespace(music=False)
print(parser.parse_args(['-m']))
# Namespace(music=True)
print(parser.parse_args('-m 1 2'.split()))
# Namespace(music=['1', '2'])
If you have only one argument to handle this way, then
arg.music = True if len(arg.music) == 0 else arg.music
is simpler. If you have many such arguments, then defining a custom action could reduce the repetition, and help ensure all those arguments are treated the same way.
What about :
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
if vars(args).get('music', False) is not False:
if not args.music:
args.music = True
print args.music
Output:
tmp:/>python arg.py
False
tmp:/>python arg.py -m
True
tmp:/>python arg.py -m 1 2 3
['1', '2', '3']
tmp:/>
The following hack after the argparse section solves your problem:
import argparse
# Same as your code above
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
# Modifies args.music: [] -> True
args.music = True if args.music==[] else args.music
print(args.music)
Tested in the command line, it gives:
$ python /tmp/blah.py -m
True
$ python /tmp/blah.py -m 1 -m 2
['2']
$ python /tmp/blah.py -m 1 2 3
['1', '2', '3']
$ python /tmp/blah.py
False

Python argument parsing get wrong result

I have a python script to parse input argument from user .my code is like this
def get_arg(argv):
result = {}
input_file=stag_db=main_tb=stag_table=main_table = "";
debug="N"
msg = ''' Syntax: dt transaction date
-i input_file (E.g. input_file.tar.gz)
-ds staging_database
-dm main_database
-ts staging_table
-tm main_table
-db debug (Y/N)'''
try:
opts, args = getopt.getopt(argv,"hd:i:ds:dm:db:ts:tm:",["ifile=","ofile="])
print args
print opts
except getopt.GetoptError:
f_end_process(msg)
for opt, arg in opts:
if opt == '-h':
f_end_process(msg)
elif opt == "-i":
input_file = arg
elif opt == "-ds":
stag_db = arg
elif opt == "-dm":
main_tb = arg
elif opt == "-ts":
stag_table = arg
elif opt == "-tm":
main_table = arg
elif opt == "-db":
debug = arg
result = {'input_file':input_file,'stag_db':stag_db,'main_tb':main_tb,'stag_table':stag_table,'main_table':main_table}
print result
if '' in result.values():
exit_status=-1
f_end_process(msg)
result['debug']= debug
return result
def main():
global input_arg
input_arg = get_arg(sys.argv[1:])
print "process started at " +strftime("%Y-%m-%d %H:%M:%S")
print input_arg
i am running code like this
python main.py -i ok.txt -ds ds_val -dm dm_val -ts tas_val -tm tm_val
i want to parse all input arguments to a list. i imported all required modules to my script
now i am able to parse only -i input.How can i parse -tm,-ts ,-dm,-ds iputs?
In an interactive Python experiment with passing various argv arrays to getopt
>>> getopt.getopt(['-hd','1'],"hd:i:ds:dm:db:ts:tm:")
([('-h', ''), ('-d', '1')], [])
You did not tell it to look for an -hd option, but rather a -h and a -d that takes an argument.
Generally for multiletter options, argument parsers expect you to use --. Your getopt should be
>>> getopt.getopt(['--hd','1'],"i:",["hd=","ds=",...])
([('--hd', '1')], [])
But, do consider argparse.
You can manage using argparse, in just a few lines.
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--input-file', '-i', type=str,
help='input file (eg: input_file.tar.gz)')
parser.add_argument('--staging-db', '-S', type=str,
help='staging database name')
parser.add_argument('--main-db', '-M', type=str,
help='main database name')
parser.add_argument('--staging-table', '-s', type=str,
help='staging table name')
parser.add_argument('--main-table', '-m', type=str,
help='main table name')
parser.add_argument('--debug', '-d', type=bool, default=False,
help="activate debug mode (defaults to False)")
args = parser.parse_args()
The parser help is generated by argparse. You can output it by typing
$ python YOURSCRIPT.py --help

Getting command line arguments as tuples in python

Here is an example of how I would like to call my script:
python script.py -f file1.txt "string1" "string2" -f file2.txt "string3" "string4"
Every file that goes as input will have 2 strings associated with that file. There can be any number of files.
To simplify, I am trying to get a print like this:
('file1.txt', 'string1', 'string2')
('file2.txt', 'string3', 'string4')
Here is what I have so far:
import sys, os, traceback, optparse
import time
import re
#from pexpect import run, spawn
def main ():
global options, args
print options.filename
#for filename in options.filename:
# print filename
#f = file(filename,'r')
#for line in f:
# print line,
#f.close()
if __name__ == '__main__':
try:
start_time = time.time()
parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), usage=globals()['__doc__'], version='$Id$')
parser.add_option ('-f', '--file', dest='filename', help='write report to FILE', metavar='FILE', nargs=3)
parser.add_option ('-v', '--verbose', action='store_true', default=False, help='verbose output')
(options, args) = parser.parse_args()
#if len(args) < 1:
# parser.error ('missing argument')
if options.verbose: print time.asctime()
main()
if options.verbose: print time.asctime()
if options.verbose: print 'TOTAL TIME IN MINUTES:',
if options.verbose: print (time.time() - start_time) / 60.0
sys.exit(0)
except KeyboardInterrupt, e: # Ctrl-C
raise e
except SystemExit, e: # sys.exit()
raise e
except Exception, e:
print 'ERROR, UNEXPECTED EXCEPTION'
print str(e)
traceback.print_exc()
os._exit(1)
With the above script, I get only the second file and related strings:
('file2.txt', 'string3', 'string4')
I think you want to use the action=append argument of the add_argument method
import argparse
parser= argparse.ArgumentParser()
parser.add_argument ('-f', '--file', nargs=3, action='append')
files = parser.parse_args('-f file1 string1 string2 -f file2 string3 string4 -f file3 string5 string6'.split()).file
for f in files:
print tuple(f)
gives you:
('file1', 'string1', 'string2')
('file2', 'string3', 'string4')
('file3', 'string5', 'string6')
Testing on cli:
with:
import argparse
parser= argparse.ArgumentParser(prog='Test', usage='%(prog)s -f Filename Option1 Option2 ')
parser.add_argument ('-f', '--file', nargs=3, action='append')
files = parser.parse_args().file
for f in files:
print tuple(f)
results:
python test.py -f file1 "foo bar" "baz" -f file2 foo bar
('file1', 'foo bar', 'baz')
('file2', 'foo', 'bar')
python test.py -f file1 "foo bar" "string2" -f file2 foo bar -f file3 "foo" "bar"
('file1', 'foo bar', 'string2')
('file2', 'foo', 'bar')
('file3', 'foo', 'bar')
python test.py -f file1 "foo bar"
usage: Test -f Filename Option1 Option2
Test: error: argument -f/--file: expected 3 argument(s)
argparse supports the notion of accumulators, which allow you to specify the same option more than once, which is probably more like what you want than anything optparse supports (your particular problem is that optparse doesn't know what to do with an argument specified multiple times, so it's "last one wins" at the command line). argparse is included in Python 2.7 and 3.2, but you should be able to download it for anything 2.6.x or later.
You weren't very clear on your constraints, but this will work for any number of -fs and other flags
import getopt
import sys
args = sys.argv[1:]
tuples = []
while args:
try:
opts, args = getopt.getopt(args, "f:v", ["file", "verbose"])
except getopt.GetoptError, err:
print str(err)
sys.exit(-1)
for o, a in opts:
if o in ("-f", "--file"):
tuples.append((a, args.pop(0), args.pop(0)))
if o in ("-v", "--verbose"):
print "yep, verbose"
print tuples
I would approach this similarly to the previous answer with a slight tweak:
import getopt
import sys
args = sys.argv[1:]
tuples = []
while args:
try:
(opts, args) = getopt.getopt(args, "f:v", ["file=", "verbose"])
except getopt.GetoptError, err:
print str(err)
sys.exit(2)
Now you can either require input in the following way:
-f file1.txt,string1,string2
And parse it in the following way:
for opt, arg in opts:
if opt in ("-f", "--file"):
tuples.append(tuple(arg.split(",")))
if opt in ("-v", "--verbose"):
print "yep, verbose"
print tuples
Or design the input as one string:
-f "file1.txt string1 string2"
and split on whatever strikes your fancy.
If you are using optparse because you want to remain compatible with python 2.6, the action='append' solution works, too:
import optparse
parser = optparse.OptionParser()
parser.add_option('-f', '--file', dest='filename', nargs=3, action='append')
Demonstration
>>> (opts, args) = parser.parse_args("-f file1.txt string1 string2 -f file2.txt string3 string4".split())
>>> for fn_tuple in opts.filename:
... print fn_tuple
('file1.txt', 'string1', 'string2')
('file2.txt', 'string3', 'string4')

Categories

Resources