如何解析由特殊预定义语法分隔的可变长度参数列表。一个例子:
./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3
使用argparse
脚本解析后,应该有三个参数:arg1
,cmdname
,arg3
。参数cmdname
应包含三个值otherscript
,a1
,a2
的列表。
有了这样的方法,可以将cmdname
中的所有内容传递给subprocess.popen(cmdname, ...)
来电。
我在考虑subparsers。但我相信一个subparser不能被阻止,并且真的与其他subparser相互排斥。还有其他任何简单的方法吗?是继承Action
的方法吗?
答案 0 :(得分:2)
正如您在帖子中指出的那样,子类化Action
可能就是这样做的方法 - 尽管如果argparse不知道otherscript
的参数,那将变得非常棘手。您可以使用parse_known_args
解决此问题,但您可能不会。老实说,我真的认为最简单的方法就是自己预处理sys.argv
。
import shlex
s = shlex.split("./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3")
def preprocess(lst):
"""
process an iterable into 2 lists.
The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
whereas the first portion contains the rest of it.
"""
argv1,argv2 = [],[]
current = argv1
for i in lst:
if i == '--cmdname':
current = argv2
elif i == '--cmdname--':
current = argv1
else:
current.append(i)
return argv1,argv2
l1,l2 = preprocess(s)
print l1
print l2
preprocess
的替代实现适用于具有.index
方法的可切片对象 - sys.argv
可以正常工作:
def preprocess(lst):
"""
process an iterable into 2 lists.
The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
whereas the first portion contains the rest of it.
"""
try:
i1 = lst.index('--cmdname')
i2 = lst.index('--cmdname--')
argv1 = lst[i1+1:i2]
argv2 = lst[:i1]+lst[i2+1:]
except ValueError:
argv1 = lst
argv2 = []
return argv1,argv2
另一个选项(在@unutbu的优秀评论中指出)是将命令行语法更改为更加标准的东西,这大大简化了问题:
./script --arg1 --cmd "otherscript --a1 --a2" --arg3
然后您可以像平常一样使用cmd
解析argparse
(为此参数指定type=shlex.split
以将字符串转换为参数列表)。
答案 1 :(得分:2)
如果我们将以--
开头的参数与以--
开头的命令部分区分开来,那将有助于argparse。
所以如果./script ++arg1 ++cmdname otherscript --a1 --a2 ++arg3
是可以接受的:
import argparse
import shlex
parser = argparse.ArgumentParser(prefix_chars = '+')
parser.add_argument('++arg1', action = 'store_true')
parser.add_argument('++arg3', action = 'store_true')
parser.add_argument('++cmdname', nargs = '*')
args = parser.parse_args(shlex.split("++arg1 ++cmdname otherscript --a1 --a2 ++arg3"))
print(args)
产量
Namespace(arg1=True, arg3=True, cmdname=['otherscript', '--a1', '--a2'])