为什么 argparse 不允许我以任何顺序添加可选参数?

Why doesn't argparse let me add optional arguments in any order?

在下面的代码中,我无法在操作(更新、黑名单、自动)之后添加 -v 和 -p 参数,可能是由于子解析器的原因。我该怎么做才能以任意顺序添加这些可选参数?

parser = argparse.ArgumentParser(usage='pyfilter.py <file> <action> <options>')
parser.add_argument('file', help='blacklist file containing IPs', type=str)

subparsers = parser.add_subparsers(help='help', dest='action')

parser_update = subparsers.add_parser('update', help='update help')

parser_blacklist = subparsers.add_parser('blacklist', help='blacklist help')

parser_auto = subparsers.add_parser('auto', help='auto help')
parser_auto.add_argument('-i', '--interval', help='interval help')

parser.add_argument('-p', '--port', help='specify the port to block', type=int)
parser.add_argument('-v', '--verbose', help='write output to screen', nargs='?')
args = parser.parse_args()

根据解析器,这是有效的:

python3.5 testfilter.py /etc/blacklist.lst -p 22 -v yes update 

而这会为 'update' 之后的每个参数产生错误:

python3.5 testfilter.py /etc/blacklist.lst update -p 22 -v yes

这就是您的解析器树的样子

parser
  |__ update
  |     |__ updateOpts
  |__ blacklist
  |__ auto
  |__ port
  |__ verbose

所以如果你做update,它会向下遍历updateOpts,在那里它找不到端口或者verbose

主解析器识别 file(必需)、--port--verbose,加上子解析器选择 {'update','auto'}.

一旦遇到 subparser 参数,它就会将解析委托给该解析器。子解析器完成后,主解析器不会继续解析。它将子解析器无法处理的字符串报告为无法识别。

因此所有用于主解析器的字符串都必须在调用子解析器之前出现。

您可以使用 parse_known_args 来解决这个问题。然后无法识别的参数将在 extras 列表中返回,这可以通过另一个解析步骤处理。

Add top level argparse arguments after subparser args

作为一条规则,argparse 试图以任何顺序允许可选(标记)参数。当有变量 narg 位置时,有一些限制,在这种情况下,有子解析器。一旦您对代码的组织方式有所了解,这种行为就有意义了。