【问题标题】:How to parse several positional arguments mixed with options?如何解析与选项混合的几个位置参数?
【发布时间】:2017-10-13 00:09:58
【问题描述】:


我需要像这样解析命令行字符串:

node frontend.js project1.pro project2.pro ... projectN.pro --spec linux-g++ CONFIG+=debug CONFIG+=qml_debug -opt1 value1 ... -opt2 value2

即选项(带连字符)和位置参数(开始时不带) 可以由用户混合:(

我尝试指定几个位置参数,但这不起作用:

parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo')
parser.add_argument('project_files', default=[], nargs='+')
parser.add_argument('-spec',  nargs=1,  required=True)
parser.add_argument('other_options',  default=[],  nargs='+')
print(parser.parse_args('--foo B project_1.pro project_2.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug'.split()))

但出现这样的错误:

PROG: error: unrecognized arguments: CONFIG+=debug CONFIG+=qml_debug

做错了什么? 谢谢!

附:抱歉,如果这个问题很愚蠢,我是 Python 和使用此类库进行参数解析的新手。
附言参数“node frontend.js”被忽略

【问题讨论】:

    标签: python argparse


    【解决方案1】:
    print(parser.parse_args('--foo B project_1.pro project_2.pro -spec linux-g++'.split()))
    

    生产

    Namespace(foo='B', other_options=['project_2.pro'], project_files=['project_1.pro'], spec=['linux-g++'])
    

    'progject_2.pro' 被分配给other_options 而不是project_files。这是因为 2 nargs='+' 的处理方式。

    parse_args 交替处理位置和可选(标记)。它试图处理尽可能多的位置。当其中一个或多个具有这些“开放式”nargs(如+*)时,这可能会导致意外结果。

    我建议改为:

    parser = argparse.ArgumentParser(prog='PROG')
    parser.add_argument('--foo')
    parser.add_argument('project_files', nargs='+')
    parser.add_argument('--spec')
    parser.add_argument('--other',  nargs='+')
    print(parser.parse_args('--foo B project_1.pro project_2.pro --spec linux-g++'.split()))
    
    print(parser.parse_args('--foo B project_1.pro project_2.pro --spec linux-g++ --other CONFIG+=debug CONFIG+=qml_debug'.split()))
    

    导致

    2343:~/mypy$ python stack46702635.py 
    Namespace(foo='B', other=None, project_files=['project_1.pro', 'project_2.pro'], spec='linux-g++')
    Namespace(foo='B', other=['CONFIG+=debug', 'CONFIG+=qml_debug'], project_files=['project_1.pro', 'project_2.pro'], spec='linux-g++')
    

    https://bugs.python.org/issue15112 - argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional

    https://bugs.python.org/issue9338 - argparse optionals with nargs='?', '*' or '+' can't be followed by positionals


    您可以省略other 参数,而使用parse_known_args。未知字符串在单独的列表中返回。

    #parser.add_argument('other',  nargs='...')
    print(parser.parse_known_args('--foo B project_1.pro project_2.pro --spec linux-g++'.split()))
    
    print(parser.parse_known_args('--foo B project_1.pro project_2.pro --spec linux-g++ CONFIG+=debug CONFIG+=qml_debug'.split()))
    
    0859:~/mypy$ python stack46702635.py 
    (Namespace(foo='B', project_files=['project_1.pro', 'project_2.pro'], spec='linux-g++'), [])
    (Namespace(foo='B', project_files=['project_1.pro', 'project_2.pro'], spec='linux-g++'), ['CONFIG+=debug', 'CONFIG+=qml_debug'])
    

    optparsegetopt 这样的早期解析器只处理标记的参数,并将其余的作为列表返回。你必须自己解析这些。

    【讨论】:

    • 那么,可以有两组或更多组位置参数,由“通常”选项分隔 - 或者 argparse 不能这样做?
    • UPD:问题是我应该支持其他应用程序的命令行格式(Qt qmake),所以我不能更改选项格式:(
    • -spec 是在两个位置之间定义的这一事实并不重要。解析由命令行中的顺序决定。关于改进这种处理存在一些错误/问题,但尚未进行正式更改。
    • 那么,如果我不能附加新选项“--other”,argparse 将无法解析我的命令行?
    • 我添加了一个parse_known_args 想法。
    猜你喜欢
    • 2017-03-31
    • 2019-12-10
    • 2015-06-19
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多