是否可以在没有任何标志的情况下使用 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
是否可以在不干扰服务器的情况下使用 Charles 代理或任何其他工具故意生成错误 500