Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional passing of arguments to methods in python

Tags:

python

I have many possible arguments from argparse that I want to pass to a function. If the variable hasn't been set, I want the method to use its default variable. However, handling which arguments have been set and which haven't is tedious:

import argparse
def my_func(a = 1, b = 2):
  return a+b

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Get the numeric values.')
    parser.add_argument('-a', type=int)
    parser.add_argument('-b', type=int)
    args = parser.parse_args()

    if not args.a is None and not args.b is None:
        result = my_func(a = args.a, b = args.b)
    elif not args.a is None and args.b is None:
        result = my_func(a = args.a)
    elif not args.b is None and args.a is None:
        result = my_func(b = args.b)
    else:
        result = my_func()

It seems like I should be able to do something like this:

result = my_func(a = args.a if not args.a is None, b = args.b if not args.b is None)

But this gives a syntax error on the comma.

I could set default values in the argparser, but I want to use the defaults set in the method definition.

like image 794
Catherine Holloway Avatar asked Jun 29 '15 18:06

Catherine Holloway


2 Answers

Use a dictionary with the kwargs unpacking syntax.

args = parser.parse_args()
result = my_func(**vars(args))

Edit

Use the SUPPRESS argument to ArgumentParser to remove empty values:

parser = argparse.ArgumentParser(description='Get the numeric values.',
                                 argument_default=argparse.SUPPRESS)
like image 84
Daniel Roseman Avatar answered Nov 03 '22 05:11

Daniel Roseman


The first solution that comes to me seems kind of hacky...but here it is.

Use inspect to write a function that looks at the arguments of a function and only passes it those arguments from args which it accepts and are not None. My guess is that this would be widely considered bad practice...

import inspect

def call_function(fn, args):
    argspec = inspect.getargspec(fn)
    arglist = {}
    for arg in argspec.args:
        if arg in args.__dict__.keys() and args.__dict__[arg] is not None:
            arglist[arg] = args.__dict__[arg]
    return fn(**arglist)

Here it is in action:

import argparse

def my_func(a=1, c=2):
    return a,c

a=None
b=2
c=3
args=argparse.Namespace(a=a,b=b,c=c)

call_function(my_func, args)

>> (1, 3)

This solution is quite under-tested and might need work to make it more robust, but the idea is there and should work in simple cases.

like image 1
Ian Hincks Avatar answered Nov 03 '22 04:11

Ian Hincks