Reputation: 16097
When using argparse
, I've not found an elegant/DRY way to use the function/method defaults instead of the defaults passed by argparse.
For example, I have foreign code I am loathe to modify. How do I tell argparse
(or elegantly handle after argparse
) to use the function defaults if the user does not pass in a clear preference on the command-line?
import argparse
def foreign_func(fav_color="blue"):
print(fav_color)
clparser = argparse.ArgumentParser()
clparser.add_argument(
"--color",
default=None,
help="Enter color")
clargs = clparser.parse_args()
foreign_func(fav_color=clargs.color)
This will print 'None', instead of "blue"
My default approach is something like:
if clparser.color:
foreign_func(fav_color=clargs.color)
else:
foreign_func()
but this seems clunky, especially if there are multiple command-line options.
EDIT: Hi folks, thank you for the fast feedback. To clarify, although it would be nice for argparse to display 'blue' in it's help, that's not my goal.
I'm looking for:
my_prog --color=red
>>> red
my_prog
>>> blue
With the code above, the program is outputting 'None', not "blue"
Upvotes: 4
Views: 270
Reputation: 16097
Combining answers/tips from @Scott Hunter, @wim, and Adam Smith, the following solution seems workable.
This solution hinges on converting the argparse NameSpace object to a dict,
then "splitting" that dict before passing to foreign_func
. Along with the argparse.SUPPRESS option, the dict passed in will have no entry for missing command-line arguments. This avoids "stomping" on foreign_func
s defaults.
Note: I have not tested this approach in the case that foreign_func
also has positional arguments, so YMMV.
import argparse
def foreign_func(fav_color="blue"):
print(fav_color)
clparser = argparse.ArgumentParser()
clparser.add_argument(
"--color",
# Use 'dest' option if your command-line option name differs
# from the function's argument name
dest="fav_color",
# 'argparse.SUPPRESS' will add an entry into the clargs "dict"
# only if the option is passed on the command-line.
default=argparse.SUPPRESS,
help="Enter color")
clargs = clparser.parse_args()
print("DBG:", vars(clargs))
foreign_func(**vars(clargs))
Testing:
python my_prog.py --color=red
>>> red
python my_prog.py
>>> blue
Upvotes: 1
Reputation: 104712
You can use inspect
to get the function's default parameter value, and use that as the default in the argparse
code.
import argparse
import inspect
def foreign_func(fav_color="blue"):
print(fav_color)
clparser = argparse.ArgumentParser()
clparser.add_argument(
"--color",
default=inspect.signature(foreign_func).parameters['fav_color'].default,
help="Enter color")
clargs = clparser.parse_args()
foreign_func(fav_color=clargs.color)
Note that this will behave a bit oddly if there is no default in the function (if it's a required parameter). In that case, the default value will be the inspect._empty
sentinel value, rather than an actually meaningful value. But your code seems to be assuming that the parameter is always optional, so I'm going with that too.
Upvotes: 3
Reputation: 49803
You can use a dictionary to specify your arguments by name; if a name is missing, that parameter will use its default. Example:
def func(a=1,b=2):
print("a=",a,"b=",b)
func()
func(**{})
func(**{'a':10})
will print
a= 1 b= 2
a= 1 b= 2
a= 10 b= 2
Upvotes: 2