Python,argparse:如何使用type = str和type = int来使用nargs = 2

Python,argparse: how to have nargs=2 with type=str and type=int

我在argparse文档上花了一些时间,但是我仍然在使用这个模块来解决我的程序中的一个选项:

1
2
3
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,如果没有给出值,则具有默认值(假设为default=50)。 我知道当预期只有一个参数时如何做到这一点,但我不知道当nargs = 2时如何进行......这甚至可能吗?


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

1
2
3
4
5
6
7
8
9
10
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

输出:

1
2
3
4
5
6
7
8
9
$ 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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

有了它,你得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> 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


对不起跳得太晚了。我会使用一个函数来调用类型。

1
2
3
4
5
6
7
8
9
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"))

我建议使用两个参数:

1
2
3
4
5
6
7
8
9
10
11
12
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

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

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