代码之家  ›  专栏  ›  技术社区  ›  dot

python argparser:如何将特定参数与特定函数相关联

  •  0
  • dot  · 技术社区  · 7 年前

    我刚接触过python和argparser库。我正试图找出如何编写一个具有许多不同函数的脚本文件,每个函数都需要不同的参数。

    例如,我可能有以下方法签名:

     def function1(a,b,c):
     def function2(x,y,z):
     def function3():
    

    到目前为止我有什么

    到目前为止,我已经添加了所有可能的参数作为可选项,如so:

    import argparse
    
     def function1(lc,uc):
         assert(lc is not None)
         assert(uc is not None)
         #do something
    
     def function2():
         #do something else
    
     def function3(lr,ur):
         assert(lr is not None)
         assert(ur is not None)
         #do something else
    
    parser = argparse.ArgumentParser(description='This is the description of my program')
    parser.add_argument('-lc','--lower_create', type=int, help='lower range value for creating mailboxes')
    parser.add_argument('-uc','--upper_create', type=int, help='upper range value for creating mailboxes')
    parser.add_argument('-lr','--lower_reserve', type=int, help='lower range value for reserving mailboxes')
    parser.add_argument('-ur','--upper_reserve', type=int, help='upper range value for reserving mailboxes')
    
    args = parser.parse_args()
    

    到现在为止,一直都还不错。当我这样运行脚本时:

     python3 myutils.py
    

    我没有任何错误。

    当我这样做的时候:

     python3 myutils.py -h
    

    它给了我一个很好的帮助系统。

    但我不清楚的是如何将特定的参数与特定的函数关联起来。这是我调用函数1时得到的错误,例如:

    lab-1:/var/www/localhost/htdocs/pvmaildbapp# python3 myutils.py function1
    usage: myutils.py [-h] [-lc LOWER_CREATE] [-uc UPPER_CREATE]
                           [-lr LOWER_RESERVE] [-ur UPPER_RESERVE]
    myutils.py: error: unrecognized arguments: function1
    

    我还是第一次在argparse文档中前进,所以我肯定我错过了一些东西。但是,任何正确方向的提示/提示都会受到赞赏

    编辑1

    基于下面来自d洹Kennetz和Utahjarhead的答案(谢谢你,btw),我修改了代码,为每个参数包含一个“dest”parm,我还需要一个arg来表示用户试图调用的函数,比如:

    parser = argparse.ArgumentParser(description='This is the description of my program')
    
    parser.add_argument('func_name',help='name of function you want to run')
    
    parser.add_argument('-lc','--lower_create', type=int, dest='lc', help='lower range value for creating mailboxes')
    parser.add_argument('-uc','--upper_create', type=int, dest='uc', help='upper range value for creating mailboxes')
    parser.add_argument('-lr','--lower_reserve', type=int, dest='lr', help='lower range value for reserving mailboxes')
    parser.add_argument('-ur','--upper_reserve', type=int, dest='ur', help='upper range value for reserving mailboxes')
    
    args = parser.parse_args()
    

    然后,我还修改了函数1的定义,如下所示:

     def function1(lc,uc):
         assert(lc is not None)
         assert(uc is not None)
         print('made it here')
         return True
    

    最后,我现在尝试通过如下命令行调用:

     python3 myutils.py function1 -lc 1 -uc 3
    

    但它根本不调用函数1。 很明显我又错过了一块拼图。

    我认为在我的代码末尾——调用parse_args()之后,我需要的是这样的:(伪代码)

    select case args.func_name
       case 'function1'
           make sure i have lc and uc
       case function3
           make sure i have lr and ur
    end select
    

    这是正确的吗?

    编辑2

    好吧,我想我已经把所有的点都连接起来了。

    1. 我确实缺少保存函数的位置参数 用户要调用的名称。
    2. 我仍在使用可选参数 用于保存lc、uc等值的符号。
    3. 我丢失的部分是用args手动匹配函数的逻辑。出于某种原因,我想我可以用argparse库免费获得一些管道。

    现在我有了这样的代码:

    args = parser.parse_args()
    #print(args)
    if args.func_name == 'function1':
        #make sure we have lc and uc
        assert(args.lc is not None)
        assert(args.uc is not None)
        function1(args.lc, args.uc)
    elif args.func_name == 'function3':
        assert(args.lr is not None)
        assert(args.ur is not None)
        function3(args.lr, args.ur)
    elif args.func_name == 'function2':
        function2()
    

    代码有效。但我觉得有一种更优雅的方式来处理我所拥有的最后一系列if/elif…随着这个实用程序文件的增长,我向它添加了更多的方法,if-elif列表将增长得相当大。

    2 回复  |  直到 7 年前
        1
  •  0
  •   d_kennetz    7 年前

    要解释哪里出错了,需要将目的地传递给argparse参数,以便在代码中作为变量调用它。其次,函数调用中使用的变量,如 def function1(lc, uc): 将是该函数的局部函数,因此它们不会被解释为全局函数。这是一件好事,因为我们通常不想将全局变量传递给函数调用(尽管有一些异常)。

    以下是我对您代码的修改:

    import argparse
    import sys
    
    parser = argparse.ArgumentParser(description='This is the description of my program')
    parser.add_argument('-lc','--lower_create', type=int, dest="lc", help='lower range value for creating mailboxes')
    parser.add_argument('-uc','--upper_create', type=int, dest="uc", help='upper range value for creating mailboxes')
    parser.add_argument('-lr','--lower_reserve', type=int, dest="lr", help='lower range value for reserving mailboxes')
    parser.add_argument('-ur','--upper_reserve', type=int, dest="ur", help='upper range value for reserving mailboxes')
    
    args = parser.parse_args()
    
    def function1(lc,uc):
        assert(lc is not None)
        assert(uc is not None)
        return True
    
    print(function1(args.lc, args.uc))
    

    首先,你看到我通过了一个叫做 dest= 在我的 parser.add_argument() 打电话。这将告诉python代码该参数将在程序中被调用。

    然后,我写了你的函数来返回 True 如果向函数传递了值。

    最后,我打电话给 print 调用我的argparse Dist= 变量的语法如下 args.lc, args.uc . 这就是如何在Python代码中调用argparse参数。

    最后,当我运行命令并传递值时:

    $ python3.5 argfun.py -lc 4 -uc 0
    

    输出:

    4
    
        2
  •  1
  •   UtahJarhead    7 年前

    您试图使用一个必需的位置参数,但在argparse设置中没有设置位置参数。要解决此问题,您似乎需要添加此额外行:

    parser.add_argument('func_name', help='function name')
    

    实际上,您已经创建了4个变量, args.lower_create , args.upper_create , args.lower_reserve , args.upper_reserve . 如果你通过了 python3 myutils.py -lc 1234 然后 args.lower_创建 值为 1234 .

    编辑:我想你可能没有包括适当的输入。它期待着类似于:

    python3 myutils.py -lc 0 -uc 1 -lr 2 -ur 3