如何将Argparse参数默认值设置为位置参数值?

时间:2014-08-25 12:51:50

标签: python argparse

我有一个发送GET请求的python脚本。它使用Argparse来获取三个参数:

  1. 地址:发送GET请求的位置
  2. 主机:要在GET请求中声明的主机
  3. 资源:正在请求的资源
  4. 示例用法可能是:

    $ python get.py 198.252.206.16 stackoverflow.com /questions/ask

    但是,在大多数情况下,只需要提供主机和资源,因为主机将解析为该地址:

     $ host -t a stackoverflow.com
     stackoverflow.com has address 198.252.206.16
    

    所需的用法可能是:

    $ python get.py stackoverflow.com /questions/ask
    

    如何设置Argparse以使Address参数的默认值为Host参数的值?


    我被要求显示当前解析参数的代码。这是:

    import argparse
    
    parser = argparse.ArgumentParser(description=
             'Send a GET request and obtain the HTTP response header and/or body.')
    
    parser.add_argument("-v", "--verbose",
                        help="Turn on verbose mode.",
                        action="store_true")
    parser.add_argument("-p", "--port",
                        type=int,
                        default=80,
                        help="Which port to use when sending the GET request."
    parser.add_argument("address",
                        help="Where to send the GET request to.")
    parser.add_argument("host",
                        help="Which Host to declare in the GET request.")   
    parser.add_argument("resource",
                        help="Which resource to request.")
    
    parser.parse_args()
    

3 个答案:

答案 0 :(得分:9)

nargs='?'很好地处理了这种情况。如果只有2个字符串,则会将其分配到hostresourceaddress会获得默认值(None)。如果有3个字符串,则会将它们分配给所有3.如果有帮助,请考虑?模式中re的行为。

解析器完成后,很容易将host值分配给address。试图在parse_args内完成任务是没有意义的(因为主机值还不知道)。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("address", nargs='?')
parser.add_argument("host")
parser.add_argument("resource")
args = parser.parse_args()

if args.address is None:
    args.address = args.host
print(args)

,用法是:

usage: get.py [-h] [address] host resource

[]整齐地标记可选的位置参数。

答案 1 :(得分:3)

如果您尝试使用ONLY位置参数来实现您所描述的行为,您可以使用像这样的列表参数(nargs):

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("args", nargs="+")
parsed = parser.parse_args()
args = parsed.args
if len(args) == 3:
    ip, host, address = args
    print ip, host, address
elif len(args) == 2:
    ip, host, address = args[0], args[0], args[1]
    print ip, host, address
else:
    print "Invalid args"

但不仅这个hacky你也失去了argparse提供的好处(你必须手动验证参数)。我建议你使用可选参数。也许是这样的:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-host", required=True)
parser.add_argument("-res", required=True)
parser.add_argument("-ip", required=False)
args = parser.parse_args()

ip = args.ip if args.ip else args.host
print args.host, args.res, ip

执行它:

python2.7 test.py -host hello -res world

答案 2 :(得分:1)

这里有两个合理的选择,你选择的取决于你使用位置参数而不是--options的依赖程度。

  1. 使用nargs='+'添加位置参数。解析args后,检查该列表的长度。如果是3,则将它们设置为地址,主机和资源。如果为2,则将它们设置为主机和资源,并从主机复制地址。否则,打印用法消息并引发异常。

  2. 将主机和资源保留为位置参数。将地址更改为选项。这意味着CLI将改为:

  3. python get.py stackoverflow.com /questions/ask --address 198.252.206.16

    您可以将默认值设置为None,然后在解析args之后检查它是否为空,我不认为在argparse中有任何设置它会自动默认为另一个位置arg。

    你选择的是个人偏好,我更喜欢2个(可选参数应该是,根据定义,选项),因为它更适合可用工具 - 如果你弯曲argparse表现得像1那么你将不得不另外覆盖--help选项,使用消息等,因为自动生成的默认值会产生误导。