Forcing getopt to process a specific option first??

D

Dan Rawson

Is there any way to force getopt to process one option first?? I'd like to be able to pass in the name of a
configuration file for my application, then have the remaining command-line parameters over-ride the configuration file
if they are present.

For the moment, I'm restricted to 2.2 versions.

TIA . . . .

Dan
 
S

Skip Montanaro

Dan> Is there any way to force getopt to process one option first?? I'd
Dan> like to be able to pass in the name of a configuration file for my
Dan> application, then have the remaining command-line parameters
Dan> over-ride the configuration file if they are present.

Not that I'm aware of. If the order of the remaining options doesn't
matter, you might try splitting the argument list before the option which
introduces your config file. For example, given this set of command line
args:

-f bar -o baz -c configfile -o bump -h

locate the '-c' and use it to split the argument list, then swap the two
pieces:
>>> s = "-f bar -o baz -c configfile -o bump -h"
>>> args = s.split()
>>> args ['-f', 'bar', '-o', 'baz', '-c', 'configfile', '-o', 'bump', '-h']
>>> index = args.index('-c')
>>> index 4
>>> args[:index], args[index:] (['-f', 'bar', '-o', 'baz'], ['-c', 'configfile', '-o', 'bump', '-h'])
>>> args = args[index:] + args[:index]
>>> args
['-c', 'configfile', '-o', 'bump', '-h', '-f', 'bar', '-o', 'baz']

Now pass that list to getopt.getopt().

If the order of the remaining arguments does matter, you just split the
argument list into three pieces, the part before rearranging:
>>> args[:index], args[index:index+2], args[index+2:] (['-f', 'bar', '-o', 'baz'], ['-c', 'configfile'], ['-o', 'bump', '-h'])
>>> args = args[index:index+2] + args[:index] + args[index+2:]
>>> args
['-c', 'configfile', '-f', 'bar', '-o', 'baz', '-o', 'bump', '-h']

Skip
 
P

Peter Otten

Dan said:
Is there any way to force getopt to process one option first?? I'd like
to be able to pass in the name of a configuration file for my application,
then have the remaining command-line parameters over-ride the
configuration file if they are present.

The easiest solution would be to make the config file the mandatory first
argument of the command line and then call

getopt.getopt(sys.argv[2:], options)

Below is another approach, that might fit your needs:

import getopt

#sample args
args = ["-c", "config.txt", "-r", "-i", "specialin.txt"]

options, args = getopt.getopt(args, "c:ri:eek::")
useroptions = dict(options)

if "-c" in useroptions:

#set defaults
defaultoptions = {"-i": "defaultin.txt", "-o": "defaultout.txt"}

del useroptions["-c"]

#override defaults
defaultoptions.update(useroptions)
options = defaultoptions.items()

print options

Peter
 
D

Dan Rawson

Skip said:
Dan> Is there any way to force getopt to process one option first?? I'd
Dan> like to be able to pass in the name of a configuration file for my
Dan> application, then have the remaining command-line parameters
Dan> over-ride the configuration file if they are present.

Not that I'm aware of. If the order of the remaining options doesn't
matter, you might try splitting the argument list before the option which
introduces your config file. For example, given this set of command line
args:

-f bar -o baz -c configfile -o bump -h

locate the '-c' and use it to split the argument list, then swap the two
pieces:
s = "-f bar -o baz -c configfile -o bump -h"
args = s.split()
args ['-f', 'bar', '-o', 'baz', '-c', 'configfile', '-o', 'bump', '-h']
index = args.index('-c')
index 4
args[:index], args[index:] (['-f', 'bar', '-o', 'baz'], ['-c', 'configfile', '-o', 'bump', '-h'])
args = args[index:] + args[:index]
args
['-c', 'configfile', '-o', 'bump', '-h', '-f', 'bar', '-o', 'baz']

Now pass that list to getopt.getopt().

If the order of the remaining arguments does matter, you just split the
argument list into three pieces, the part before rearranging:
args[:index], args[index:index+2], args[index+2:] (['-f', 'bar', '-o', 'baz'], ['-c', 'configfile'], ['-o', 'bump', '-h'])
args = args[index:index+2] + args[:index] + args[index+2:]
args
['-c', 'configfile', '-f', 'bar', '-o', 'baz', '-o', 'bump', '-h']

Skip
Thanks! Either this solution or the one Peter Otten proposed will work . . .

Wow, two good solutions in an hour . . . .

Dan
 
J

Jeff Epler

Care for another solution?

I'd simply do two passes over the argument list. This has an advantage
over both the other alternatives proposed. First, it works if the user
writes something like "-bccf" (equivalent to the arguments ["-b", "-c", "cf"]),
and second it works with repeated options like [-a", "x", "-a", "y"].

This doesn't work if something in the configuration file could affect
the available set of commandline switches. There may be some other
shortcoming I haven't considered yet, too.

Jeff

########################################################################
# Program
import getopt

def main(argv):
args, rest = getopt.getopt(argv, "c:a:b")

# First pass, parse any -c option
for k, v in args:
if k == "-c":
print "Using config file", v

# Next, parse the other options
for k, v in args:
if k == "-c": continue
print "Processing switch", k, v


print "Remaining positional arguments", rest
argv = "-a x -bccf -a y ...".split()
main(argv)

########################################################################
# Output
Using config file cf
Processing switch -a x
Processing switch -b
Processing switch -a y
Remaining positional arguments ['...']
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top