【问题标题】:Is it possible to use argparse to capture an arbitrary set of optional arguments?是否可以使用 argparse 来捕获任意一组可选参数?
【发布时间】:2023-08-27 07:52:01
【问题描述】:

是否可以使用argparse 来捕获任意一组可选参数?

例如,以下两个都应该被接受为输入:

python script.py required_arg1 --var1 value1 --var2 value2 --var3 value3

python script.py required_arg1 --varA valueA --var2 value2 --varB valueB

先验我不知道将指定接收哪些可选参数,但会相应地处理它们。

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    这是一种 hackish 方式,但效果很好:

    检查,没有添加哪些参数并添加它们

    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("foo")
    parser.add_argument("-bar", type=int)
    # parser can have any arguments, whatever you want!
    
    parsed, unknown = parser.parse_known_args() # this is an 'internal' method
    # which returns 'parsed', the same as what parse_args() would return
    # and 'unknown', the remainder of that
    # the difference to parse_args() is that it does not exit when it finds redundant arguments
    
    for arg in unknown:
        if arg.startswith(("-", "--")):
            # you can pass any arguments to add_argument
            parser.add_argument(arg.split('=')[0], type=<your type>, ...)
    
    args = parser.parse_args()
    

    例如:

    python3 arbitrary_parser.py ha -bar 12 -extra1 value1 -extra2 value2
    

    那么结果就是

    args = Namespace(bar=12, foo='ha', extra1='value1' extra2='value2')
    

    【讨论】:

    • 较早的答案之一使用了parse_known_args,但随后使用sys.argvunknown 解析样式。我喜欢您将这些标志添加到解析器并重新解析的想法。骇人听闻的要求需要骇人听闻的解决方案。 :)
    • 谢谢你的堆栈@MrP01 这是使用界面的一种非常干净的方式。并且让我们仍然在一个地方对格式错误的任意参数进行过滤。
    【解决方案2】:

    可能吗?可能,但我不会推荐它。 argparse 不是解析此类输入的最佳工具,或者相反,从 argparse 的角度来看,这是一个糟糕的参数规范。

    您是否想过usage 行应该是什么样子?如何向您的用户解释这一点?

    你将如何直接从sys.argv 解析这个工作?看起来你可以收集 3 件:

     prog = sys.argv[0]
     arg1 = sys.argv[1]
     keys = sys.argv[2::2]
     # maybe strip -- off each
     values = sys.argv[3::2]
     kvdict = {k:v for k, v in zip(keys, values)}
    

    还有其他关于通用 key:value 对的 SO 问题。比如:

     --args key1:value1 key2:value2
    

    这可以通过nargs='*' 和一个将:(或=)上的每个输入字符串拆分并通过key 存储内容的操作来处理。

    您的要求最不适合argparse 使用,因为它需要绕过将参数标志与argv 中的字符串匹配的整个想法。它需要以某种方式关闭所有正常的argparse 解析。

    看起来我几年前提出了同样的建议

    Parse non-pre-defined argument

    或更早

    Using argparse to parse arguments of form "arg= val"

    【讨论】:

      最近更新 更多