<p>似乎是一个很酷的问题<code>argparse</code>允许您以两种方式扩展它的回调,一种是针对自定义类型的<code>type=...</code>,另一种是针对自定义行为的<code>action=...</code>。我认为上述问题在<code>type=</code>中是不可能的,所以我使用了一个涉及<code>action=</code>的解决方案</p>
<p>编写自定义操作的基本方法包括从<code>argparse.Action</code>继承和重写<code>__call__</code>(以及可选的<code>__init__</code>)</p>
<p>下面是实现您的想法的一个开始,您可能需要扩展/更改它(例如,在action类中调用<code>super().__call__(...)</code>以处理基本行为(对于类型等)可能是有意义的)。我只使用了最简单的方法来满足您的问题。你知道吗</p>
<pre class="lang-py prettyprint-override"><code>import argparse
import pprint
class GroupAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
group, = values
namespace._current_group = group
groups = namespace.__dict__.setdefault('groups', {})
if group in groups:
raise argparse.ArgumentError(self, f'already specified: {group}')
groups[group] = {}
class AppendToGroup(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
value, = values
if not getattr(namespace, '_current_group', None):
raise argparse.ArgumentError(self, 'outside of group!')
namespace.groups[namespace._current_group][self.dest] = value
parser = argparse.ArgumentParser()
parser.add_argument(' group', action=GroupAction)
parser.add_argument(' opt1', action=AppendToGroup)
parser.add_argument(' opt2', action=AppendToGroup)
parser.add_argument(' opt3', action=AppendToGroup)
pprint.pprint(parser.parse_args().groups)
</code></pre>
<p>注意,这里我使用<code>namespace</code>来存储状态,所以不幸的是,最后你会得到一点额外的<code>args._current_group</code>。你知道吗</p>
<p><code>__dict__.setdefault</code>有点鬼鬼祟祟,所以我来解释一下,这是一种略短的写作方式:</p>
<pre class="lang-py prettyprint-override"><code>if not hasattr(namespace, 'groups'):
namespace.groups = {}
groups = namespace.groups
</code></pre>
<p>我使用的基本策略是存储当前组,并在看到其他参数时附加到该组</p>
<p>以下是实际操作的示例:</p>
<pre><code>$ python3.7 t.py group 1 opt1 a opt2 b opt3 c
{'1': {'opt1': 'a', 'opt2': 'b', 'opt3': 'c'}}
$ python3.7 t.py group 1 opt1 a opt2 b opt3 c group 2
{'1': {'opt1': 'a', 'opt2': 'b', 'opt3': 'c'}, '2': {}}
$ python3.7 t.py group 1 opt1 a opt2 b opt3 c group 2 opt3 c
{'1': {'opt1': 'a', 'opt2': 'b', 'opt3': 'c'}, '2': {'opt3': 'c'}}
$ python3.7 t.py group 1 group 1
usage: t.py [-h] [ group GROUP] [ opt1 OPT1] [ opt2 OPT2] [ opt3 OPT3]
t.py: error: argument group: already specified: 1
$ python3.7 t.py opt1 a group 1
usage: t.py [-h] [ group GROUP] [ opt1 OPT1] [ opt2 OPT2] [ opt3 OPT3]
t.py: error: argument opt1: outside of group!
</code></pre>