通过一些内省,可以从函数的签名中设置
ArgumentParser
,从而直接将命令行参数映射到函数参数:
import argparse
import inspect
def myfun(mode, count=1, frobify=False, *files):
print('Doing %s %d times on %s (%sfrobifying)' % (
mode, count, files, '' if frobify else 'not '
))
def funopt(fun, argv=None):
parser = argparse.ArgumentParser()
if hasattr(inspect, 'getfullargspec'):
spec = inspect.getfullargspec(fun)
else:
spec = inspect.getargspec(fun)
num_defaults = len(spec.defaults) if spec.defaults is not None else 0
for i in range(len(spec.args)):
if i < len(spec.args) - num_defaults:
parser.add_argument(spec.args[i])
elif spec.defaults[i - len(spec.args)] is False:
parser.add_argument('--' + spec.args[i],
default=False, action='store_true')
else:
default = spec.defaults[i - len(spec.args)]
parser.add_argument('--' + spec.args[i],
default=default,
type=type(default))
if spec.varargs is not None:
parser.add_argument(spec.varargs,
nargs='*')
kwargs = vars(parser.parse_args(argv))
args = []
for arg in spec.args:
args += [kwargs[arg]]
if spec.varargs is not None:
args += kwargs[spec.varargs]
fun(*args)
funopt(myfun)
结果:
$ python test.py
usage: test.py [-h] [--count COUNT] [--frobify] mode [files [files ...]]
test.py: error: too few arguments
$ python test.py myaction a b c
Doing myaction 1 times on ('a', 'b', 'c') (not frobifying)
$ python test.py --frobify --count=5 myaction a b c
Doing myaction 5 times on ('a', 'b', 'c') (frobifying)
argparse
时遇到困难,请再次发布问题。 - Ianargparse
,我很快会想出一个答案。 - Moon Cheesezargparse
,但它能让用可选参数调用脚本变得更容易。 - chepner