我正在尝试对参数进行分组,以便用户可以执行以下操作:
python sample.py scan -a 1 -b 2
or
python sample.pt save -d /tmp -n something
这是我的代码:
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='this is the description'
)
parser.add_argument('op', choices=['scan','save'], help='operation', default='scan')
root_group = parser.add_mutually_exclusive_group()
group1 = root_group.add_argument_group('g1', 'scan')
group1.add_argument('-a', help='dir1')
group1.add_argument('-b', help='dir2')
group2 = root_group.add_argument_group('g2', 'save')
group2.add_argument('-d', help='dir')
group2.add_argument('-n', help='name')
args = parser.parse_args()
print args
我运行python sample.py --help
我收到了一个错误。有人可以告诉我如何解决它吗?
Traceback (most recent call last):
File "sample.py", line 18, in <module>
args = parser.parse_args()
File "C:\Python27\lib\argparse.py", line 1688, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "C:\Python27\lib\argparse.py", line 1720, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "C:\Python27\lib\argparse.py", line 1926, in _parse_known_args
start_index = consume_optional(start_index)
File "C:\Python27\lib\argparse.py", line 1866, in consume_optional
take_action(action, args, option_string)
File "C:\Python27\lib\argparse.py", line 1794, in take_action
action(self, namespace, argument_values, option_string)
File "C:\Python27\lib\argparse.py", line 994, in __call__
parser.print_help()
File "C:\Python27\lib\argparse.py", line 2313, in print_help
self._print_message(self.format_help(), file)
File "C:\Python27\lib\argparse.py", line 2287, in format_help
return formatter.format_help()
File "C:\Python27\lib\argparse.py", line 279, in format_help
help = self._root_section.format_help()
File "C:\Python27\lib\argparse.py", line 209, in format_help
func(*args)
File "C:\Python27\lib\argparse.py", line 317, in _format_usage
action_usage = format(optionals + positionals, groups)
File "C:\Python27\lib\argparse.py", line 388, in _format_actions_usage
start = actions.index(group._group_actions[0])
IndexError: list index out of range
如果我添加action ='store_const',则错误消失,并且发生新错误,要求输入4个。
答案 0 :(得分:3)
Argparse
似乎并不完全支持将群组添加到其他群组中。发生此错误是因为Argparse
要求root_group
进行某种操作。解决方法是向组添加参数:
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='this is the description'
)
# This is now redundant. We can remove it
# parser.add_argument('op', choices=['scan','save'], help='operation', default='scan')
root_group = parser.add_mutually_exclusive_group()
# Workaround
root_group.add_argument('--scan', help='scan', action='store_true')
root_group.add_argument('--save', help='save', action='store_true')
group1 = root_group.add_argument_group('g1', 'scan')
group2 = root_group.add_argument_group('g2', 'save')
group1.add_argument('-a', help='dir1')
group1.add_argument('-b', help='dir2')
group2.add_argument('-d', help='dir', default='')
group2.add_argument('-n', help='name')
args = parser.parse_args()
print args
请注意,我们正在使用--scan
和--save
。为避免使用--
前缀,您可能需要Sub-commands
的帮助。可以找到详细信息here。
答案 1 :(得分:2)
格式化usage
行时出错,并且是root_group
没有任何_group_actions
的结果。我从其他bug问题中知道使用格式化程序很脆弱。
argument_groups
和mutually_exclusive_groups
不适合嵌套。尽管名称相近(和阶级遗产),但它们的目的却截然不同。 argument_groups
控制help
行的显示。 mutually_exclusive_groups
控制使用情况显示,并引发错误。
在您的情况下,添加到group1
和group2
的参数添加到主解析器列表中,但未添加到root_group
用于排他性检查(或使用格式)的列表中)。
如果我直接向root_group
添加参数,help
有效,并产生:
In [19]: parser.print_help()
usage: ipython3 [-h] [-a A] [-b B] [-d D] [-n N] [--foo FOO] {scan,save}
this is the description
positional arguments:
{scan,save} operation
optional arguments:
-h, --help show this help message and exit
--foo FOO
您可以从相关的&#39;中看到。侧边栏上有很多人询问有关向mutually_exclusive_groups
添加参数组的问题。一个允许具有各种逻辑条件的嵌套组的补丁在将来还有很长的路要走。
但是,正如您所发现的那样,subparser机制可以很好地处理您的特定情况。
您不需要使用parents
机制:
sp = parser.add_subparsers()
sp_scan = sp.add_parser('scan', help='scans directories')
sp_scan.add_argument('-a', '--a', help='first num', required=True)
sp_scan.add_argument('-b', '--b', help='second num', required=True)
sp_save = sp.add_parser('save', parents=[save_parser], help='saves something')
sp_save.add_argument('-d', '--d', help='directory path', required=True)
sp_save.add_argument('-n', '--n', help='name of the file', required=True)
parents
机制在这里工作,但更适用于解析器在别处定义(和导入),或在多个子分析器中重用的情况。例如,如果你有许多子分享器共享一组核心参数(以及它们自己独特的参数)。
答案 2 :(得分:1)
感谢@ skyline上面的链接,我让它与subparsers合作:
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='this is the description'
)
scan_parser = argparse.ArgumentParser(add_help=False)
scan_parser.add_argument('-a', '--a', help='first num', required=True)
scan_parser.add_argument('-b', '--b', help='second num', required=True)
save_parser = argparse.ArgumentParser(add_help=False)
save_parser.add_argument('-d', '--d', help='directory path', required=True)
save_parser.add_argument('-n', '--n', help='name of the file', required=True)
sp = parser.add_subparsers()
sp_scan = sp.add_parser('scan', parents=[scan_parser], help='scans directories')
sp_save = sp.add_parser('save', parents=[save_parser], help='saves something')
args = parser.parse_args()
print args