在python的命令行中解析带有参数的多个列表



我正在编写一个程序,它应该接受多个文件作为输入,其中每个文件都给出了一个参数列表。调用可以是这样的:

python myprog.py  
--file picture1.svg --scale 3 --color false 
--file picture2.svg --scale 1 --color false 
--file pictureX.svg --scale 11 --color true 
-o output.svg

在我的例子中,文件的顺序和参数的正确分组当然都很重要。所以我希望最终能收到一个字典

[["file":"picture1.svg", "scale":3, "color":"false"],
["file":"picture2.svg", "scale":1, "color":"false"],
["file":"pictureX.svg", "scale":11, "color":"true"]]

---------------------------------------//------------------------------

目前我发现的是:

  1. 使用action ="append"使用argparse。
import argparse
parser = argparse.ArgumentParser(description='Call file list with parameters')
parser.add_argument('-f', '--file', type=str, nargs='+', action='append',  help='file list')
parser.add_argument('-o', '--output', type=str,  help='output file')
args = parser.parse_args()
print(args)

调用看起来像:

python myprog.py  
--file picture1.svg scale:3 color:false 
--file picture2.svg scale:1 color:false 
--file pictureX.svg scale:11 color:true 
-o output.svg

这将给我一个包含三个列表的列表,理论上我可以解析

[["picture1.svg", "scale:3", "color:false"],
["picture2.svg", "scale:1", "color:false"],
["picturex.svg", "scale:11", "color:true"]]

对于argparse的自动帮助生成来说,这不是最佳的工作方式,不允许声明默认值,等等。否则对我来说似乎是最优的解决方案

  1. 另一种方法是生成参数列表,如
parser.add_argument('-c', '--color', type=str, nargs='+', action='append',  help='color list')
parser.add_argument('-s', '--scale', type=int, nargs='+', action='append', help='scale list')

可以这样调用:

python myprog.py  
--file picture1.svg --scale 3 --color false 
--file picture2.svg --scale 1 --color false 
--file pictureX.svg --scale 11 --color true 
-o output.svg

导致列表的列表:

[["picture1.svg", "picture2.svg", "picturex.svg"],
["scale:3", "scale:1", "scale:11"],
["color:false","color:false", "color:true"]]

优点是通过argparse处理一切。但是,如果缺少某些参数(例如第二个分数),则不能保证参数之间的对应关系。

  1. 我看到的最后一个可能性是使用json作为输入。它可以很容易地解析为我们想要的对象。但是,命令行解析器的所有优点将消失。

你认为最优的解决方案是什么,上面的一个,还是我忽略了什么,还有另一种优雅的方法?谢谢你!

嗯,我想我找到了一个方法,应该是通过argparse。

可以使用自己的数据类型作为命令行参数。参照上面的问题,我们可以创建一个类,类似于:

class Filetype():
patterns = {
'filename': re.compile(".*.svg"),
'scale': re.compile("scale:(d+.*d*)"),
'color': re.compile("color:(True|False)+"),
}
def __call__(self, value):
a = self.patterns["filename"].match(value)
if a:
return {"file": value}
a=self.patterns["scale"].match(value)
if a:            
return {"scale": a.group(1)}
a=self.patterns["color"].match(value)
if a:
return {"color": a.group(1)}

raise argparse.ArgumentTypeError(
"'{}' should be either: (1) a file name (*.svg), (2) 'scale:FLOAT' parameter, or (3) 'code:[True|False]'".format(
value))
return value

现在,让我们向解析器添加一个参数。"type"参数执行工作

parser.add_argument('-f', '--file', type=Filetype(), nargs='+', action='append',
help='list of file names with parameters')

我们现在可以用:

python myprog.py  
--file picture1.svg scale:3 color:false 
--file picture2.svg scale:1 color:false 
--file pictureX.svg scale:11 color:true 
-o output.svg

这似乎是一个更好的妥协。虽然我们必须自己执行简单的检查,但仍然可以产生有意义的错误消息,argparse仍然为我们做繁重的工作

最新更新