使用argparse
我希望能够将可选参数与多个位置参数混合,例如svn
允许:
svn ls first/path -r 1000 second/path
目前,Python尚未正式支持(c.f。http://bugs.python.org/issue14191)。我写了这个解决方法,我现在想知道,如果a)有更好/更容易/更优雅的方式来做到这一点,并且b)如果有人可以在代码中看到可能在某些情况下破坏它的东西:
#!/usr/bin/env python3
import argparse as ap
p = ap.ArgumentParser()
p.add_argument('-v', action='store_true')
p.add_argument('-l', action='store_true')
p.add_argument('files', nargs='*', action='append')
p.add_argument('remainder', nargs=ap.REMAINDER, help=ap.SUPPRESS)
args = p.parse_args()
while args.remainder != []:
args = p.parse_args(args.remainder, args)
print(args)
用法示例:
./test.py a b -v c d
输出:
Namespace(files=[['a', 'b'], ['c', 'd']], l=False, remainder=[], v=True)
答案 0 :(得分:2)
您可以使用parse_known_args代替remainder
:
import argparse as ap
p = ap.ArgumentParser()
p.add_argument('-v', action='store_true')
p.add_argument('-l', action='store_true')
p.add_argument('files', nargs='*', action='append')
args, unknown = p.parse_known_args()
while unknown:
args, unknown = p.parse_known_args(unknown, args)
print(args)
产量
Namespace(files=[['a', 'b'], ['c', 'd']], l=False, v=True)
答案 1 :(得分:0)
您想要files=[['a', 'b'], ['c', 'd']]
还是files=['a', 'b', 'c', 'd']
?换句话说应该
./test.py a b -v c d
./test.py a b -v c -l d
./test.py -l a b -v c d
提供不同的files
列表清单。
append
位置的 *
通常没有意义,因为您无法重复位置参数。但是使用这个递归应用程序,它确实有效。但如果子列表很重要,为什么不使用多个位置参数。
另一方面,要获得“文件”的平面列表,您可以做几件事:
您可以在解析后展平列表(例如args.files=list(itertools.chain(*args.files))
)
您可以使用p.add_argument('files', nargs='?', action='append')
。这会迭代每个file
字符串。
./test.py a b -l c d -v e f
Namespace(files=['a', 'b', 'c', 'd', 'e', 'f'], l=True, remainder=[], v=True)
您可以通过从初始解析中删除位置来复制http://bugs.python.org/issue14191补丁。在这种情况下,extras
可以简单地插入args
。
这样做的一个缺点是usage
和help
对位置一无所知,需要自定义usage
和/或description
参数。
usage = usage: %(prog)s [-h] [-v] [-l] [files [files ...]]
description = 'files: may be given in any order'
p = ap.ArgumentParser(usage=usage, description=description)
p.add_argument('-v', action='store_true')
p.add_argument('-l', action='store_true')
args, extras = p.parse_known_args()
args.files = extras
unutbu的答案不保留分组。他们第一次失败了:
命名空间(files = [['a','b'],['c','d','e','f']],l = True,v = True)
可以改为提供一个单一的列表:
p = ap.ArgumentParser()
p.add_argument('-v', action='store_true')
p.add_argument('-l', action='store_true')
p.add_argument('files', nargs='*')
args, unknown = p.parse_known_args()
args.files.extend(unknown)
不需要迭代,因为第一次处理optionals
。 unknown
中剩下的所有内容都是files
。
总之 - 为了保留分组,您的解决方案似乎是最好的。