有没有办法按照定义的顺序获取 argparse 的参数?

Is there a way to get the argument of argparse in the order in which they were defined?

我想打印程序的所有选项,为了便于阅读,它们被分组。但是,当通过 vars(args) 访问参数时,顺序是随机的。

argparse 解析 sys.argv[1:] 中的参数列表(sys.argv[0] 用作 usage 中的 prog 值)。

args=parser.parse_args() returns 一个 argparse.Namespace 对象。 vars(args) returns 基于此对象 (args.__dict__) 的字典。字典的键是无序的。 print(args) 也使用这个字典顺序。

解析器为了自己的簿记目的保留了所见操作的记录。但是它不暴露给用户,是一个无序的set。我可以想象定义一个自定义 Action 子类,记录其实例的使用顺序。


可以按照创建解析器时定义参数的顺序检索参数。那是因为 parser 有一个包含所有 Actions_actions 列表。它不是 public API 的一部分,而是一个基本属性,不太可能每次都消失。

举例说明:

In [622]: parser=argparse.ArgumentParser()
In [623]: parser.add_argument('foo')
In [624]: parser.add_argument('--bar')
In [625]: parser.add_argument('--baz')

In [626]: parser.print_help()
usage: ipython3 [-h] [--bar BAR] [--baz BAZ] foo

positional arguments:
  foo

optional arguments:
  -h, --help  show this help message and exit
  --bar BAR
  --baz BAZ

用法和帮助列表按照参数定义的顺序显示参数,除了 positionalsoptionals 是分开的。

In [627]: args=parser.parse_args(['--bar','one','foobar'])
In [628]: args
Out[628]: Namespace(bar='one', baz=None, foo='foobar')
In [629]: vars(args)
Out[629]: {'bar': 'one', 'baz': None, 'foo': 'foobar'}

In [631]: [(action.dest, getattr(args,action.dest, '***')) for action in parser._actions]
Out[631]: [('help', '***'), ('foo', 'foobar'), ('bar', 'one'), ('baz', None)]

我在这里迭代 _actions 列表,为每个 Action 获取 dest,并从 args 命名空间获取该值。我也可以从 vars(args) 字典中获取它。

我不得不给 getattr 一个默认值 ***,因为 help 操作没有出现在命名空间中。我本可以从显示中过滤掉那种操作。