我有一个特定的脚本,它通常用2个位置参数和一堆可选参数来调用。
script.py <file1> <file2>
我想添加另一个子分析器,当我传递可选参数时应该调用它。
script.py -file_list <files.list>
基本上,我需要的是,当传递-file_list
时,解析器不应该查找file1
和file2
。我不希望默认情况需要另一个选项来调用它(因为默认情况已经在使用中,因此我不想破坏它(。
我试着保持默认解析器的原样,并为-file_list
创建子解析器。但是解析器仍然期望位置参数file1
和file2
。
示例代码(这不能像我希望的那样工作(:
args = argparse.ArgumentParser()
#default arguments
args.add_argument("file1", type=str)
args.add_argument("file2", type=str)
#subparser for file_list
file_list_sp = args.add_subparsers()
file_list_parser = file_list_sp.ad_parser("-file_list")
file_list_parser.add_argument("file_list")
all_args = args.parse_args()
也许我需要为默认情况创建一个单独的子分析器;但所有子解析器似乎都需要一个额外的命令来调用它们。我希望当-file_list未通过时自动调用默认情况
您在传递其他选项时提到,所以我认为保留argparse
有很好的动机。假设没有其他职位,你可以试试:
In [23]: parser = argparse.ArgumentParser()
In [24]: parser.add_argument('--other'); # other optionals
In [25]: parser.add_argument('--filelist');
In [26]: parser.add_argument('files', nargs='*');
这接受"--filelist",而不需要位置文件(结果是空列表(:
In [27]: parser.parse_args('--filelist alist'.split())
Out[27]: Namespace(other=None, filelist='alist', files=[])
其他文件-但将该列表限制为2需要您自己在解析后进行测试:
In [28]: parser.parse_args('file1 file2'.split())
Out[28]: Namespace(other=None, filelist=None, files=['file1', 'file2'])
但它也接受这两种形式。同样,你自己的解析后代码将不得不整理出冲突的消息:
In [29]: parser.parse_args('file1 file2 --filelist xxx'.split())
Out[29]: Namespace(other=None, filelist='xxx', files=['file1', 'file2'])
你必须处理两者都不提供的情况:
In [30]: parser.parse_args('--other foobar'.split())
Out[30]: Namespace(other='foobar', filelist=None, files=[])
帮助:
In [32]: parser.print_help()
usage: ipykernel_launcher.py [-h] [--other OTHER] [--filelist FILELIST]
[files ...]
positional arguments:
files
optional arguments:
-h, --help show this help message and exit
--other OTHER
--filelist FILELIST
因此,我所创建的内容接受这两种形式的输入,但不限制它们。
我尝试使用mutually_exclusive_group,但它只适用于nargs='?'
。我曾经认为nargs='*'
在一个小组中工作,但要么我的记忆有问题,要么有一个补丁改变了事情。m-x组中的位置必须具有"required=False"值。
CCD_ 10实际上是一种特殊的CCD_。因此,如果您使用"prog file1 file2{cmd1,cmd2}"创建解析器,则在检查第三个字符串之前,它仍然需要这两个文件名。包括subparsers
在内的所有positionals
都是按位置处理的,而不是按值处理的。标记的参数(optional
(可以按任何顺序出现,但不会覆盖positionals
。
如果您首先定义subparsers
,那么第一个位置必须是其中一个命令。subparsers
不是必需的(默认情况下(,但这不会改变对其他位置的处理。
工作互斥组
如果我们还指定了一个default
,那么nargs='*'
确实有效。这是一个未记录的细节。我把它忘了,直到我看了代码(特别是_get_positional_kwargs
方法(。*
被标记为required
,除非它被赋予default
。前段时间在一个或多个bug/问题中已经讨论过了。
因此可以使位置列表和"--file_list"互斥
In [71]: parser = argparse.ArgumentParser()
In [72]: parser.add_argument('--other'); # other optionals
In [73]: group = parser.add_mutually_exclusive_group(required=True)
In [74]: group.add_argument('--file_list');
In [75]: group.add_argument('files', nargs='*', default=[]);
良好案例:
In [76]: parser.parse_args('--other foobar file1 file2'.split())
Out[76]: Namespace(other='foobar', file_list=None, files=['file1', 'file2'])
In [77]: parser.parse_args('--other foobar --file_list file3'.split())
Out[77]: Namespace(other='foobar', file_list='file3', files=[])
如果两者都使用:
In [78]: parser.parse_args('--other foobar --file_list file3 file1 file2'.split())
usage: ipykernel_launcher.py [-h] [--other OTHER] [--file_list FILE_LIST]
[files ...]
ipykernel_launcher.py: error: argument files: not allowed with argument --file_list
如果两者都不提供:
In [79]: parser.parse_args('--other foobar'.split())
usage: ipykernel_launcher.py [-h] [--other OTHER] [--file_list FILE_LIST]
[files ...]
ipykernel_launcher.py: error: one of the arguments --file_list files is required
现在的用法看起来像:
In [81]: parser.print_usage()
usage: ipykernel_launcher.py [-h] [--other OTHER] [--file_list FILE_LIST]
[files ...]
它仍然无法控制文件的数量——除非必须至少有一个。