我有一个python脚本,它是C ++构建系统的一部分 - 它读取C ++文件并使用libclang
来提取一些元数据,这些元数据在某处存储为json。
我们在一些非常大的文件中使用这个工具。我们希望能够将其与ccache
一起使用。要做到这一点,python脚本需要"看起来像" gcc
在命令行上,足够接近ccache
可以把它想象成一些高度非标准的c编译器碰巧产生json而不是目标代码。 (我们已经传递了很多c-compiler标志,无论如何需要经过libclang
。)
因为我们必须改变解析其参数的方式,所以我将其更改为使用argparse
,因为我不知道如何使用argparse
做我需要的工作。问题在于我是否有一种聪明的方式,我没有想到/不知道如何更热火地做这件事。
该工具需要从命令行解析输入文件路径和输出文件路径。输出文件路径使用-o
发出信号,输入文件路径可以使用-c
发出信号。 (类似于gcc
的工作原理......)所有其他标志应该收集在另一个列表中,该列表将转发到libclang
。
示例:
./args.py foo bar -o baz -c qaz
input: qaz
output: baz
parser_args: ['foo', 'bar']
./args.py foo bar -c qaz -o baz
input: qaz
output: baz
parser_args: ['foo', 'bar']
皱纹是它还需要支持一种奇怪的顺序,其中-o
选项出现在-c
和参数-c
之间。
./args.py foo bar -c -o baz qaz
input: qaz
output: baz
parser_args: ['foo', 'bar']
这是我在天真(公认的C-ish)python中掀起的解析器:
#!/usr/bin/env python
import sys
def help():
print """
This tool takes command line arguments in a way compatible with gcc. This is
so that it can be compatible with ccache.
Pass with -c the path to the rtdv file.
Pass with -o the output path to the json file.
All other args are forwarded to libclang.
To accomodate ccache, the following syntax is also allowed:
-c -o output input
"""
def parse_cl_args(argv):
input = False
output = False
parser_args = []
i = 1
while i < len(argv):
# When we see -c, go into a mode where next parameter is the source file,
# except that -o and its argument are allowed to appear inbetween
if argv[i] == '-c':
i+=1
# Consume any -o immediately after -c
while argv[i] == '-o':
if output:
raise Exception("Too many output files specified: " + output + " , " + argv[i+1])
output = argv[i+1]
i+=2
# Consume -c parameter as input file
if input:
raise Exception("Too many input files specified: " + input + " , " + argv[i])
input = argv[i]
i+=1
elif argv[i] == '-o':
if output:
raise Exception("Too many output files specified: " + output + " , " + argv[i+1])
output = argv[i+1]
i+=2
else:
parser_args += [argv[i]]
i+=1
return (input, output, parser_args)
def main():
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) <= 1:
help()
return
(input, output, parser_args) = parse_cl_args(sys.argv)
# if not input:
# sys.stderr.write('Argv: ' + str(sys.argv) + '\n')
# raise Exception("Must use -c flag to specify input file to parse.")
#
# if not output:
# sys.stderr.write('Argv: ' + str(sys.argv) + '\n')
# raise Exception("Must use -o flag to specify output path for json")
print 'input: ', input
print 'output: ', output
print 'parser_args: ', parser_args
if __name__ == '__main__':
main()
有没有一种很好的方法可以使用argparse
做这样的事情?
我对argparse的尝试就是这样:
-c
使用subparser并为其添加-o
选项-o
选项。尝试将-o
的两个版本分配给同一个变量。parse_known_args
收集不匹配的parser_args
。问题在于我不确定如何在此策略中为-c
配置subparser。一旦我将subparser命名为-c
,我就可以为其添加-o
选项,但我不确定如何让它收集它应该关联的令牌与args.c
。从文档中我也不清楚它将如何与parse_known_args
进行交互。
无论如何,最终结果不必与我给出的代码示例相同。例如,只有在-c
和-o
之前出现的参数被收集为parser_args
而其他参数被丢弃或其他内容时,这是可以的。
只有真的需要以ccache
将调用它的方式工作。如果argparse产生的帮助是可以理解的,那就太好了。