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, tracebac开发者_如何学JAVAk, 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 -f
s 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')
精彩评论