首页 > 解决方案 > 解析互斥的可选参数和位置参数,后跟传递参数

问题描述

我正在尝试模拟 Python 解释器命令行行为,如帮助文本所示:

command [options] [-m mod | file] [arg] ...

那是:

我曾尝试使用内置的 argparse 模块,但没有成功。

import argparse

parser = argparse.ArgumentParser()

selector = parser.add_mutually_exclusive_group(required=True)
selector.add_argument('file', nargs='?', help='path to script')
selector.add_argument('-m', help='module name')

parser.add_argument('args', nargs=argparse.REMAINDER)

parser.parse_args(['-m', 'hello', '--', 'arg1'])

运行这个产生

usage: test.py [-h] [-m M] [file] ...
test.py: error: argument file: not allowed with argument -m

这是有道理的,因为 argparse 似乎通常忽略选项的顺序 - 解析选项后剩余的任何位置参数都会按照指定从第一个到最后一个填充位置参数。

我已经尝试定义 customargparse.Action来完成这项工作,但它最终看起来很 hacky,因为与Action组中的一个参数相对应的类需要保存一个累积值以供以后包含在args.

我也尝试过对 的输入进行预处理parser.parse_args,但不喜欢这种方法,因为有关哪些选项具有值(以区分选项参数与file参数)以及哪些选项是终端参数组的一部分的信息(应该考虑传递参数的开头[arg] ...)将在argparse.add_argument... 调用和预处理代码之间重复。

什么是一个好的方法(除了需要提供例如路径之外-f)?

附加约束:

标签: pythonargparse

解决方案


即使没有相互排斥的分组,fileargs不能很好地一起玩:

In [2]: parser = argparse.ArgumentParser()                                           
In [3]: parser.add_argument('-m');                                                    
In [4]: parser.add_argument('file', nargs='?');                                      
In [6]: parser.add_argument('args', nargs=argparse.REMAINDER);   

好的:

In [7]: parser.parse_args('-m foo a b c '.split())                                   
Out[7]: Namespace(args=['b', 'c'], file='a', m='foo')

'--' 只是让我们使用 '-b' 作为纯字符串:

In [8]: parser.parse_args('-m foo a -- -b c '.split())                               
Out[8]: Namespace(args=['-b', 'c'], file='a', m='foo')

'a' 去 'file',休息到 'args' - 这是因为所有的 'contiguous' 位置都是一起评估的。使用remainder,该-m标志将被忽略,并被视为纯字符串。

In [9]: parser.parse_args('a -m foo -- -b c '.split())                               
Out[9]: Namespace(args=['-m', 'foo', '--', '-b', 'c'], file='a', m=None)
In [10]: parser.parse_args('a -- -b c '.split())                                     
Out[10]: Namespace(args=['-b', 'c'], file='a', m=None)

参数分配甚至在Action调用之前就发生了,因此自定义 Action 类不会改变这种行为。

标记参数为您提供最好的控制 - 对顺序和互斥性。


推荐阅读