using optparser

J

jimgardener

hi
I have a program which I call findmatch that expects these arguments
1.a person name
2.a group name
3.an integer
4.a float value

I thought I would allow user to call this program either using options
or using positional arguments in a predefined order
ie,
findmatch -f schoolmates -i jon -t 3.5 -n 115
or
findmatch jon schoolmates 115 3.5

I tried to code this using optparser..

def parse_arguments():
usage = """usage: %prog [options]
eg:
findmatch -i jon -f schoolmates -n 115 -t 3.5
"""
parser = OptionParser(usage)

parser.add_option('-i','--person',dest='personname',help='person
to be matched')
parser.add_option('-f','-group',dest='groupname', help='group
containing people to be tested against')
parser.add_option('-n','--
num',dest='samplenumber',type='int',help='how many samples to be used
')
parser.add_option('-t','--
cutoff',dest='cutoff',type='float',help='some upperlimit ')

options,args = parser.parse_args()

def check_if_person_name_valid(name):
if not person_exists(name):
parser.error('you must give an valid person name')
def check_if_group_name_valid(name):
if not group_exists(name):
parser.error('you must give a valid group')

if not options.personname or not options.groupname:
print parser.format_help()
parser.exit()
check_if_person_name_valid(options.personname)
check_if_group_name_valid(options.groupname)

return options

iif __name__=='__main__':
options = parse_arguments()
person_name = options.personname
group = options.groupname
number_of_samples_to_use = options.samplenumber
cutoff = options.cutoff
msg = 'You are trying to match {0} against group {1} using {2}
samples \
and using {3:2.2f} as the upper limit '
print msg.format(person_name , group , number_of_samples_to_use ,
cutoff )


This can handle keyword arguments.But if I have to allow a user to
input arguments without options
ie
findmatch jon schoolmates 115 3.5

can I do this in the above method? If user enters the above line ,the
options instance would have
{ 'personname': None ,'groupname': None ...}
and
args will contain a list of positional arguments .

I am not sure how this can be processed so that a user is given
freedom to choose either.
Any suggestions most welcome.
regards,
jim
 
C

Chris Hulan

hi
I have a program which I call  findmatch that expects these arguments
1.a person name
2.a group name
3.an integer
4.a float value

I thought I would allow user to call this program either using options
or using positional arguments in a predefined order
ie,
findmatch  -f schoolmates -i jon -t 3.5 -n 115
or
findmatch jon schoolmates 115 3.5

I tried to code this using optparser..

def parse_arguments():
    usage = """usage: %prog [options]
    eg:
    findmatch -i jon -f schoolmates   -n 115 -t 3.5
    """
    parser = OptionParser(usage)

    parser.add_option('-i','--person',dest='personname',help='person
to be matched')
    parser.add_option('-f','-group',dest='groupname', help='group
containing people to be tested against')
    parser.add_option('-n','--
num',dest='samplenumber',type='int',help='how many samples to be used
')
    parser.add_option('-t','--
cutoff',dest='cutoff',type='float',help='some upperlimit ')

    options,args = parser.parse_args()

    def check_if_person_name_valid(name):
        if not person_exists(name):
            parser.error('you must give an valid person name')
    def check_if_group_name_valid(name):
        if not group_exists(name):
            parser.error('you must give a valid group')

    if not options.personname or not options.groupname:
        print parser.format_help()
        parser.exit()
    check_if_person_name_valid(options.personname)
    check_if_group_name_valid(options.groupname)

    return options

iif __name__=='__main__':
    options = parse_arguments()
    person_name = options.personname
    group = options.groupname
    number_of_samples_to_use = options.samplenumber
    cutoff = options.cutoff
    msg = 'You are trying to match {0} against group {1} using {2}
samples \
and using {3:2.2f} as the upper limit '
    print msg.format(person_name ,  group , number_of_samples_to_use ,
cutoff )

This can handle keyword arguments.But if I have to allow a user to
input arguments without options
ie
findmatch jon schoolmates 115 3.5

can I do this in the above method? If user enters the above line ,the
options instance would have
{  'personname': None ,'groupname': None ...}
and
args will contain a list of positional arguments .

I am not sure how this can be processed so that a user is given
freedom to choose either.
Any suggestions most welcome.
regards,
jim

You could check if args has 4 elements, assuming they are the
positional args just assign them to the options
Or you could check the command line to see if there are any items
starting with '-', and then proceed accordingly.
 
J

Jonathan Gardner

hi
I have a program which I call  findmatch that expects these arguments
1.a person name
2.a group name
3.an integer
4.a float value

I thought I would allow user to call this program either using options
or using positional arguments in a predefined order
ie,
findmatch  -f schoolmates -i jon -t 3.5 -n 115
or
findmatch jon schoolmates 115 3.5

I tried to code this using optparser..

def parse_arguments():
    usage = """usage: %prog [options]
    eg:
    findmatch -i jon -f schoolmates   -n 115 -t 3.5
    """
    parser = OptionParser(usage)

    parser.add_option('-i','--person',dest='personname',help='person
to be matched')
    parser.add_option('-f','-group',dest='groupname', help='group
containing people to be tested against')
    parser.add_option('-n','--
num',dest='samplenumber',type='int',help='how many samples to be used
')
    parser.add_option('-t','--
cutoff',dest='cutoff',type='float',help='some upperlimit ')

    options,args = parser.parse_args()

    def check_if_person_name_valid(name):
        if not person_exists(name):
            parser.error('you must give an valid person name')
    def check_if_group_name_valid(name):
        if not group_exists(name):
            parser.error('you must give a valid group')

    if not options.personname or not options.groupname:
        print parser.format_help()
        parser.exit()
    check_if_person_name_valid(options.personname)
    check_if_group_name_valid(options.groupname)

    return options

iif __name__=='__main__':
    options = parse_arguments()
    person_name = options.personname
    group = options.groupname
    number_of_samples_to_use = options.samplenumber
    cutoff = options.cutoff
    msg = 'You are trying to match {0} against group {1} using {2}
samples \
and using {3:2.2f} as the upper limit '
    print msg.format(person_name ,  group , number_of_samples_to_use ,
cutoff )

This can handle keyword arguments.But if I have to allow a user to
input arguments without options
ie
findmatch jon schoolmates 115 3.5

can I do this in the above method? If user enters the above line ,the
options instance would have
{  'personname': None ,'groupname': None ...}
and
args will contain a list of positional arguments .

I am not sure how this can be processed so that a user is given
freedom to choose either.
Any suggestions most welcome.
regards,
jim

Jim, the secret sauce here is the "args" result from the parsing.

What you do is you check to see if the args length is expected, and
then grab args in the order you want. Then you can stick them in the
options.

IE:

if len(args) == 4:
options['personname'] = args[0]
options['groupname'] = args[1]
... etc ...

I don't know how you want to resolve what happens if they use the
options and ordered args. As a general rule of thumb, I try to keep
the two separate. Options should be optional, while ordered args are
not.
 
M

Michele Simionato

Accepting both options and positional arguments for the same purpose
does not look like a good idea to me.
Anyway, here is a solution using plac (http://pypi.python.org/pypi/
plac) assuming you can afford an external dependency:

import plac

@plac.annotations(
personname=("person to be matched", 'option', 'i'),
groupname=("group containing people to be tested against",
'option', 'f'),
samplenumber=("how many samples to be used", 'option', 'n', int),
cutoff=("some upperlimit", 'option', 't'))
def main(personname, groupname, samplenumber, cutoff, *args):
# the implementation below does not allow mixing options and args
# it works only if you give no options and the needed 4 arguments
if (personname is None and groupname is None and samplenumber is
None
and cutoff is None): # no options given, look at the arguments
try:
personname, groupname, samplenumber, cutoff = args
except ValueError:
plac.parser_from(main).error('Not enough arguments (got %d
of 4)'
% len(args))
return personname, groupname, samplenumber, cutoff

if __name__ == '__main__':
import plac; print plac.call(main)
 

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,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top