rockymonkey555
rockymonkey555

Reputation: 8340

Passing an argument to main that calls a function in python

I'm trying to pass arguments to my python script using argparse and consequently call functions. Any ideas where I might be going wrong?

def parse_args():
      parser = argparse.ArgumentParser()
      parser.add_argument('-d','--d', dest='action', action='store_const',const=do_comparison, 
                        help="Diff the current and most recent map file memory information)")   

      options = parser.parse_args()

      return options

def do_comparison(parsed_args):
    # do things


def main(args):    
    options = parse_args()

if __name__ == '__main__':
    sys.exit(main())

Upvotes: 0

Views: 5351

Answers (1)

hpaulj
hpaulj

Reputation: 231385

In my comment I missed the fact that you are using store_const and const=do_comparison. So you are trying some sort of callback.

options from parse_args is a argparse.Namespace object. This is a simple object, similar to a dictionary. In fact vars(options) returns a dictionary.

When main is run (with -d), options.action will be set to the const, a function. But remember, in Python, functions are first class objects, and can be set to variables, etc just like numbers and strings. To be used the function has to be 'called'.

options.action()

should end up calling do_comparison. Actually since that function requires an argument, you should use

options.action(options)

or some other way of providing a varible or object to the function.

Of course you'll have to be careful about the case where you don't specify -d. Then options.action will have the default value (e.g. None). If the default isn't a callable, then this call will produce an error.

The argparse documentation illustrates this kind of action in the section dealing with subparsers (subcommands). I vaguely recall a tutorial that set an argument value to functions like add and multiply, creating a simple arithmetic expression evaluator.

Usually the values in the Namespace are strings, or numbers, and to use them you test for string equality. e.g.

 if options.action is None:
     # default action
 elif options.action == 'print':
     print(options)
 else:
     do some other backup or error

A callback kind of action is possible, and may be convenient in some cases, but it isn't the usual arrangement.


You asked about using successfully store a string following the -d, to be used as the function arg with:

parser.add_argument('-d','--d', dest='action', dest='function_input', action='store_const', const=diff_map) 

A 'store_const' action does not take an argument (in effect nargs=0). It's more like store_true. In fact store_true is just a store_const with has default=False and const=True.

What you need is another argument, whick could occur either before or after the -d. argparse tries to be order flexible.

Here's a simple script with a callable argument, and flexible positional argument.

import argparse
def action1(*args):
 print 'action1',args
def action0(*args):
 print 'action0',args

parser = argparse.ArgumentParser()
parser.add_argument('-d', dest='action', action='store_const', const=action1, default=action0)
parser.add_argument('args', nargs='*')
args = parser.parse_args()
args.action(args.args)

resulting runs

1238:~/mypy$ python stack32214076.py 
action0 ([],)
1238:~/mypy$ python stack32214076.py one two three
action0 (['one', 'two', 'three'],)
1238:~/mypy$ python stack32214076.py one two three -d
action1 (['one', 'two', 'three'],)
1239:~/mypy$ python stack32214076.py -d one two three
action1 (['one', 'two', 'three'],)
1239:~/mypy$ python stack32214076.py -d
action1 ([],)

TO make -d value perform some action on value, try:

parser.add_argument('-d','--action')

The default action type stores one value (e.g. action='store', nargs=None)

args = parser.parse_args()
if args.action:  # or is not None
     do_comparison(args.action)

If -d is not given args.action will have default None value, and nothing happens here.

If -d astr is given acts.action will have the string value 'astr'. This if just calls the do_comparison function with this value. It's the present of this (nondefault) value that triggers the function call.

This is a rather straight forward use of a parser and an argument.

Upvotes: 1

Related Questions