是否可以在没有任何标志的情况下使用 argparse?

Posted

技术标签:

【中文标题】是否可以在没有任何标志的情况下使用 argparse?【英文标题】:Would it be possible to use argparse without any flags? 【发布时间】:2019-05-21 03:23:32 【问题描述】:

是否可以在没有任何标志的情况下使用argparse

例如,只要没有提供任何标志(在本例中为 -u-i),我希望脚本将第一个参数 sys.argv[1] 处理为 IP 地址。

代码

import argparse, sys

parser = argparse.ArgumentParser()

parser.add_argument('-u')
parser.add_argument('-i')

args = parser.parse_args()

if args.i:
    print("IP Address is " + args.i)
elif args.u:
    print("URL is " + args.u)
elif len(sys.argv) > 1: 
    print("IP Address is " + sys.argv[1])
else: 
    print("No arguments ")

正常输出

C:\>python script.py
No arguments

C:\>python script.py 8.8.8.8
usage: script.py [-h] [-u U] [-i I]
script.py: error: unrecognized arguments: 8.8.8.8

C:\>python script.py -i 8.8.8.8
IP Address is 8.8.8.8

C:\>

即使没有提供标志(-u-i),我也希望输出。

C:\>python script.py 8.8.8.8
IP Address is 8.8.8.8

C:\>python script.py -i 8.8.8.8
IP Address is 8.8.8.8

如果有更好的选择,请告诉我。

【问题讨论】:

python script.py 1.2.3.4 -i 5.6.7.8 怎么样?我不认为你可以直接在argparse 中轻松地做到这一点,我会考虑对它产生的对象进行后处理。 【参考方案1】:

您可以使用ArgumentParser.parse_known_args()

import argparse
parser = argparse.ArgumentParser()

parser.add_argument('-u')
parser.add_argument('-i')

args, ip = parser.parse_known_args()

if args.i:
    print("IP Address is " + args.i)
elif args.u:
    print("URL is " + args.u)
elif ip:
    print("IP Address is " + ip[0])
else:
    print('No argument provided')

这样做的缺点是它不会显示在帮助中(除非您将它包含在某处或修改HelpFormatter)。


另一种解决方案是使用互斥组,其位置参数使用nargs='?'

import argparse, sys

parser = argparse.ArgumentParser()

parser.add_argument('-u')
group = parser.add_mutually_exclusive_group()

group.add_argument('-i')
group.add_argument('ip', nargs='?')

args = parser.parse_args()

if args.i:
    print("IP Address is " + args.i)
elif args.ip:
    print("IP Address is " + args.ip)
elif args.u:
    print("URL is " + args.u)
else:
    print('No argument provided')

因此,当尝试同时指定位置参数和 -i 时,您会收到错误:

$ script.py 2.3.4.5 -i 1.2.3.4
usage: script.py [-h] [-u U] [-i I | ip]
p.py: error: argument -i: not allowed with argument ip

这将表明您可以使用 -i IP 或位置参数,尽管语法对于不习惯命令行的人来说可能有点难以阅读:

$ script.py -h
usage: script.py [-h] [-u U] [-i I | ip]

positional arguments:
  ip

optional arguments:
  -h, --help  show this help message and exit
  -u U
  -i I

【讨论】:

很好,+1,这看起来是正确的方法! parse_known_arguments() 的另一个缺点是 argparse 不会在无法识别的内容上出错......它只会通过它。这可能不是你真正想要的行为。 @JohnSzakmeister 在 Op 的 MWE 中,他们没有检查 IP 有效性或其他任何东西。显然你会检查长度并解析 IP。 @GiacomoAlzetta 这不是我的意思。 parse_known_arguments() 会将未知选项作为参数而不是错误传递。这不仅仅是检查 IP 有效性(没有任何解决方案提供)的问题,它错过了 argparse 可以为您提供的错误处理。我希望这是有道理的。尝试将 --foo --bar 1.2.3.4 传递给 parse_known_args() 并查看行为。它不会在--foo--bar 上出错......它留给你处理它。为另一个工具编写一个包装器很好,但在其他情况下它就不够用了。 @JohnSzakmeister 我认为您不了解parse_known_args 的工作原理。解析器不知道的参数在结果的第二个元素中提供。正如我所说,完整的解决方案将验证 IP,因此 --foo--bar 将触发验证错误。请注意,您可能会定义一个ipaddress 函数来指定选项的type,因此您所要做的就是调用它,oyu 将收到相同的错误消息。【参考方案2】:

你可以这样做:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('-i', dest='type', action='store_const',
                    const='ip', default='ip')
parser.add_argument('-u', dest='type', action='store_const',
                    const='url')

parser.add_argument('location', nargs='?', default=None)

args = parser.parse_args()

if args.location is not None:
    if args.type == 'ip':
        print("IP Address is " + args.location)
    elif args.type == 'url':
        print("URL is " + args.location)
else:
    print("No argument provided")

在这里,我们使用选项来指定类型并使位置成为必需参数。该类型将默认为ip,因此它提供了您需要的默认行为,但您可以更明确地使用-i-u

【讨论】:

没有参数就失败了 @SergeBallesta 也许你可以解释更多你想要什么?您可以添加nargs='?'。我更新了代码。 @JohnSzakmeister:抱歉,我没有正确阅读您的答案。请忘记(并原谅)我之前的评论。

以上是关于是否可以在没有任何标志的情况下使用 argparse?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在没有任何训练的情况下使用 Caffe Only 进行分类?

sed 就地标志,适用于 Mac (BSD) 和 Linux

是否可以在没有默认数据库的情况下使用 Laravel 4

是否可以在不干扰服务器的情况下使用 Charles 代理或任何其他工具故意生成错误 500

是否可以在不使用 android studio 中的任何 USB 电缆的情况下通过 wifi 进行调试? [复制]

在无需分叉的情况下模拟任何 SIGHASH 标志