【问题标题】:Use argparse to call different functions使用 argparse 调用不同的函数
【发布时间】:2022-02-17 18:17:28
【问题描述】:

我是 Argparse 模块的新手。我几乎完成了我的脚本,但有些事情我找不到办法。

这是脚本:

import argparse

def function1(a, b, c):
    #mystaff
def function2(e, f):
    #mystaff
def function3(g):
    #mystaff

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='blahblah')
    parser.add_argument('-a','--a', help='blahblah', required=False, default="defaultvalue")
    parser.add_argument('-b','--b', help='blahblah', required=False)
    .......

    args = parser.parse_args()
    function1(args.a,args.b,args.c)

我想从命令提示符调用脚本。现在,我可以使用它来调用function1python myscript.py -a <var>

我想要的是:

python myscript.py -a <var>:按原样调用function1

python myscript.py function2 -c <var>:只调用函数2

python myscript.py function3 -g <var>: 只调用函数3

所以,如果我不指定函数,function1 是默认值,否则我也必须从命令提示符传递函数名称。有什么想法吗?

【问题讨论】:

  • 如果 argparse 不是严格要求,您可以查看 click (click.pocoo.org),它允许这样的嵌套命令。

标签: python argparse


【解决方案1】:

默认子命令

如果你想有子命令,如果没有指定子命令,则将其中一个设为默认,那么你不能使用典型的子解析器方法。

您需要分两次执行 argparse:

parser = ArgumentParser()
parser.add_argument("function", 
                    nargs="?",
                    choices=['function1', 'function2', 'function2'],
                    default='function1',
                    )
args, sub_args = parser.parse_known_args()

if args.function == "function1":
    parser = ArgumentParser()
    parser.add_argument('-a','--a')
    parser.add_argument('-b','--b')
    parser.add_argument('-c','--c')
    args = parser.parse_args(sub_args)
    function1(args.a, args.b, args.c)
elif args.function == "function2":
    ...
elif args.function == "function3":
    ...

处理--help

如果你想让--help 选项有用,你需要做更多的工作:

  • 我们需要手动处理帮助,因为有时我们需要整体帮助,有时我们需要子命令的帮助
  • 我们不能立即给出默认子命令,因为我们需要能够判断它是否被指定

这应该可以解决问题:

# Parse the subcommand argument first
parser = ArgumentParser(add_help=False)
parser.add_argument("function", 
                    nargs="?",
                    choices=['function1', 'function2', 'function2'],
                    )
parser.add_argument('--help', action='store_true')
args, sub_args = parser.parse_known_args(['--help'])

# Manually handle help
if args.help:
    # If no subcommand was specified, give general help
    if args.function is None: 
        print parser.format_help()
        sys.exit(1)
    # Otherwise pass the help option on to the subcommand
    sub_args.append('--help')

# Manually handle the default for "function"
function = "function1" if args.function is None else args.function

# Parse the remaining args as per the selected subcommand
parser = ArgumentParser(prog="%s %s" % (os.path.basename(sys.argv[0]), function))
if function == "function1":
    parser.add_argument('-a','--a')
    parser.add_argument('-b','--b')
    parser.add_argument('-c','--c')
    args = parser.parse_args(sub_args)
    function1(args.a, args.b, args.c)
elif function == "function2":
    ...
elif function == "function3":
    ...

【讨论】:

  • 是的。我在官方文档中看到了该功能。但问题是如何将第一个函数指定为默认值,而不传递其名称,而其他函数仅在命令中使用它们的名称。
  • 我在没有帮助的情况下选择了第一个选项,因为它更容易理解。但是,当我从命令python myscript.py 调用时没有任何内容并希望运行function1,我在if function == 'function1' 行中有一个错误,该函数未定义
  • 在第一个选项中,该行是if args.function == 'function1',您缺少args
  • 我试图将解决方案与--help 一起使用,似乎args.help 在执行args, sub_args = parser.parse_known_args(['--help']) 后将始终为真。不应该只是 args, sub_args = parser.parse_known_args() 而不是吗?
【解决方案2】:

你可以这样做。使用 set_defaults(func = your_function)

   _parser = argparse.ArgumentParser(description="blalbabla awesome Framework")
   _subparsers = _parser.add_subparsers(help="sub command help")
   _check_parser = _subparsers.add_parser("check", help="check the code")
   _check_parser.add_argument("--script_path", help="can be a python file or dir", required=True)
   _check_parser.add_argument("--verbose", help='turn on debug level logging', action='store_true', default=False)
   _check_parser.set_defaults(func=do_function) 

   def  do_function(args):
     if args.script_path is file:
       xxxx

然后你就可以正确访问 do_function()

【讨论】:

【解决方案3】:

我假设您需要根据用户通过 cmd 传递的输入参数调用不同的函数。 这是添加子解析器的一种方法。

import argparse

def function1(args):
"""
:description: This function creates function-1.
:arguments: args: input arguments added by user
"""
    print("Input path given by user: "+ args.input_path)
    print("No. of Iterations: " + str(args.iterations))

def function2(args):
"""
:description: This function creates function-2.
:arguments: args: input arguments added by user
"""
    print("Time specified by user: "+ str(args.time) + " mins")

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Test helper')
    subparsers = parser.add_subparsers(help='Commands')

    # Arguments for running FUNCTION-1
    parser_0 = subparsers.add_parser('function1', help='Running func1...')
    parser_0.add_argument('-itr', dest='iterations', required=False, default=1, action="store",
                           help='No of iterations (integer value). DEFAULT=1')
    parser_0.add_argument('-p', dest='input_path', required=True, default="C:/Temp", action="store",
                           help='Input path. DEFAULT=C:/Temp')
    parser_0.set_defaults(func=function1)

    # Arguments for running FUNCTION-2
    parser_1 = subparsers.add_parser('function2', help='Running func2...')
    parser_1.add_argument('-time', required=False, dest='time', default=None, action="store",
                           help="Time in minutes. DEFAULT=No time set.")
    parser_1.set_defaults(func=function2)

    args = parser.parse_args()
    if args.func:
        args.func(args)

现在您可以像这样通过 cmd 提供参数:

>python mycode.py function1 -itr 3 -p C:/Users/abcxyz
Input path given by user: C:/Users/abcxyz
No. of Iterations: 3

>python mycode.py function2 -time 5
Time specified by user: 5 mins

【讨论】:

    【解决方案4】:
    parser.add_argument('-a','--a', dest='action', action='store_const', const=function1)
    

    要调用您需要添加的特定功能const=function1

    你可以看到这个problem以获得正确答案

    【讨论】:

      猜你喜欢
      • 2019-11-29
      • 2011-06-30
      • 2011-03-28
      • 2018-01-22
      • 2022-12-29
      • 2023-01-06
      • 2011-06-05
      • 2018-12-09
      相关资源
      最近更新 更多