【问题标题】:Python,argparse: how to have nargs=2 with type=str and type=intPython,argparse:如何使用 type=str 和 type=int 获得 nargs=2
【发布时间】:2013-06-02 06:50:23
【问题描述】:

我花了一些时间在 argparse 文档上,但我仍然在为我的程序中的一个选项而努力使用这个模块:

parser.add_argument("-r", "--rmsd", dest="rmsd", nargs=2,
    help="extract the poses that are close from a ref according RMSD",
    metavar=("ref","rmsd"))

我希望第一个参数是一个字符串(类型为str)并且是强制的,而第二个参数的类型应该是int,如果没有给出值,则有一个默认值(比如说@987654324 @)。当只需要一个参数时,我知道该怎么做,但是当 nargs=2 时我不知道该怎么做……这可能吗?

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    我建议使用两个参数:

    import argparse
    
    parser = argparse.ArgumentParser(description='Example with to arguments.')
    
    parser.add_argument('-r', '--ref', dest='reference', required=True,
                        help='be helpful')
    parser.add_argument('-m', '--rmsd', type=int, dest='reference_msd',
                        default=50, help='be helpful')
    
    args = parser.parse_args()
    print args.reference
    print args.reference_msd
    

    【讨论】:

      【解决方案2】:

      您可以执行以下操作。 required 关键字将字段设置为必填,default=50 将选项的默认值设置为 50(如果未指定):

      import argparse
      
      parser = argparse.ArgumentParser()
      
      parser.add_argument("-s", "--string", type=str, required=True)
      parser.add_argument("-i", "--integer", type=int, default=50)
      
      args = parser.parse_args()    
      print args.string
      print args.integer
      

      输出:

      $ python arg_parser.py -s test_string
          test_string
          50
      $ python arg_parser.py -s test_string -i 100
          test_string
          100
      $ python arg_parser.py -i 100
          usage: arg_parser.py [-h] -s STRING [-i INTEGER]
          arg_parser.py: error: argument -s/--string is required
      

      【讨论】:

        【解决方案3】:

        我倾向于同意 Mike 的解决方案,但这是另一种方式。这并不理想,因为用法/帮助字符串告诉用户使用 1 个或多个参数。

        import argparse
        
        def string_integer(int_default):
            """Action for argparse that allows a mandatory and optional
            argument, a string and integer, with a default for the integer.
        
            This factory function returns an Action subclass that is
            configured with the integer default.
            """
            class StringInteger(argparse.Action):
                """Action to assign a string and optional integer"""
                def __call__(self, parser, namespace, values, option_string=None):
                    message = ''
                    if len(values) not in [1, 2]:
                        message = 'argument "{}" requires 1 or 2 arguments'.format(
                            self.dest)
                    if len(values) == 2:
                        try:
                            values[1] = int(values[1])
                        except ValueError:
                            message = ('second argument to "{}" requires '
                                       'an integer'.format(self.dest))
                    else:
                        values.append(int_default)
                    if message:
                        raise argparse.ArgumentError(self, message)            
                    setattr(namespace, self.dest, values)
            return StringInteger
        

        这样,你会得到:

        >>> import argparse
        >>> parser = argparse.ArgumentParser(description="")
        parser.add_argument('-r', '--rmsd', dest='rmsd', nargs='+',
        ...                         action=string_integer(50),
        ...                         help="extract the poses that are close from a ref "
        ...                         "according RMSD")
        >>> parser.parse_args('-r reference'.split())
        Namespace(rmsd=['reference', 50])
        >>> parser.parse_args('-r reference 30'.split())
        Namespace(rmsd=['reference', 30])
        >>> parser.parse_args('-r reference 30 3'.split())
        usage: [-h] [-r RMSD [RMSD ...]]
        : error: argument -r/--rmsd: argument "rmsd" requires 1 or 2 arguments
        >>> parser.parse_args('-r reference 30.3'.split())
        usage: [-h] [-r RMSD [RMSD ...]]
        : error: argument -r/--rmsd: second argument to "rmsd" requires an integer
        

        【讨论】:

        • 感谢您的回答,我想避免创建尽可能多的选项,但我认为这确实是最简单的方法!
        【解决方案4】:

        抱歉来晚了。我会使用一个函数来调用类型。

        def two_args_str_int(x):
            try:
                return int(x)
            except:
                return x
        
        parser.add_argument("-r", "--rmsd", dest="rmsd", nargs=2, type=two_args_str_int
            help="extract the poses that are close from a ref according RMSD",
            metavar=("ref","rmsd"))
        

        【讨论】:

          【解决方案5】:

          我遇到了类似的问题,但是“使用两个参数”方法对我不起作用,因为我需要一个配对列表:parser.add_argument('--replace', nargs=2, action='append'),如果我使用单独的参数,那么我将不得不验证列表的长度等。 这是我所做的:

          1. tuple 用于metavar 以正确显示帮助:tuple=('OLD', 'NEW') 导致帮助字符串显示为--replace OLD NEW。它已记录在案,但在尝试不同的选项之前我找不到它。
          2. 使用自定义验证:在parse_args 之后,验证结果列表的项目,如果出现问题,请调用parser.error()。那是因为它们具有不同的数据类型。

          【讨论】:

            猜你喜欢
            • 2018-06-29
            • 2017-08-13
            • 1970-01-01
            • 1970-01-01
            • 2015-11-14
            • 2014-10-11
            • 2016-10-26
            • 1970-01-01
            • 2015-07-17
            相关资源
            最近更新 更多