【问题标题】:Parsing multiple lists with parameters from the command line in python从python中的命令行使用参数解析多个列表
【发布时间】:2021-12-07 11:36:56
【问题描述】:

我正在编写一个程序,它应该将多个文件作为输入,其中为每个文件提供一个参数列表。调用可能如下所示:

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. 通过 argparse 使用 action="append"。
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 作为输入。它可以很容易地解析成我们想要的对象。但是,命令行解析器的所有优势都将消失。

您认为最佳解决方案是上述中的一个,还是我忽略了某些事情而有另一种优雅的方法可以做到这一点? 谢谢!

【问题讨论】:

    标签: python list command line argparse


    【解决方案1】:

    好吧,我想我找到了一种应该是 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
    

    现在,让我们为解析器添加一个参数。 “类型”参数完成工作

     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 仍然为我们完成繁重的工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      • 2013-03-06
      • 2020-01-25
      • 2021-11-05
      • 2013-01-22
      相关资源
      最近更新 更多