【问题标题】:parsing non GNU-standard options using optparse in python在 python 中使用 optparse 解析非 GNU 标准选项
【发布时间】:2013-03-25 19:38:17
【问题描述】:

出于某种原因,我的程序有非标准命令行选项。我的程序也有一个长选项,只有一个“-”。例如,有效的命令行选项是“-f”/“-foo”。短选项和长选项都需要有一个由空格或“=”分隔的参数。

我正在尝试使用 optparse 对其进行解析,但我知道 optparse 不支持非 GNU 标准选项。有没有办法调整 optparse 来做到这一点?

【问题讨论】:

  • 注意:自 python 2.7 版起,不鼓励使用 optparse。 optparse 模块已弃用,不会进一步开发; argparse 模块将继续开发。有关详细信息,请参阅 [PEP 0389][1]。 [1]:python.org/dev/peps/pep-0389
  • @shakaran:小技巧,你可以在 cmets 中使用[inline link format](http://example.com)(显示为inline link format)来建立链接。
  • 谢谢!我将在下一个评论链接中使用它。不幸的是,据我所知,我无法编辑我的最后一条评论。

标签: python arguments command-line-arguments optparse


【解决方案1】:

我认为没有任何方法可以调整 optparse(虽然我不确定),但 getopt 是您可以处理 C 样式命令行选项的替代方案。

【讨论】:

    【解决方案2】:

    来自optparse documentation

    选项:
    用于提供额外信息以指导或定制程序执行的参数。选项有许多不同的语法;传统的 Unix 语法是连字符 (“-”) 后跟一个字母,例如-x-F。此外,传统的 Unix 语法允许将多个选项合并到一个参数中,例如-x -F 等价于 -xF。 GNU 项目引入了--,后跟一系列连字符分隔的单词,例如--file--dry-run这是 optparse 提供的仅有的两种选项语法

    (强调)

    所以不,您不能使用optparse 指定其他处理参数的方式。但是,您可以使用sys module 中的argv 自己解析参数。

    这将是更多的工作,但它可能看起来像:

    from sys import argv
    for arg in argv:
        if arg.startswith("-") or arg.startswith("--"):
            # Parse the argument
    

    【讨论】:

    • 感谢您的回复。我已经想到了这一点,但我想知道是否有办法使用 optparse 来做到这一点。现在,我正在使用 parser.add_option 添加一个普通的长选项。然后我修改 argv 以在长选项之前附加一个 - 以便 optparse.OptionParser 可以解析它。例如:parser.add_option("--foo",dest="foo")。如果命令行选项是 -foo,我会解析它并将其设为“--foo”并将其作为参数发送给解析器函数。但这里的问题是,在帮助中它会将选项打印为--foo,但我希望它为-foo。我可以更改帮助文本吗?
    【解决方案3】:

    这是一种稍微有点骇人听闻的方式来做你需要的事情。

    子类OptionOptionParser并修补一些方法:

    from optparse import Option, OptionError, OptionParser
    
    class MyOption(Option):
        def _set_opt_strings(self, opts):
            for opt in opts:
                if len(opt) < 2:
                    raise OptionError(
                        "invalid option string %r: "
                        "must be at least two characters long" % opt, self)
                elif len(opt) == 2:
                    self._short_opts.append(opt)
                else:
                    self._long_opts.append(opt)
    
    class MyOptionParser(OptionParser):
        def _process_args(self, largs, rargs, values):
            while rargs:
                arg = rargs[0]
                if arg == "--":
                    del rargs[0]
                    return
                elif arg[0:2] == "--":
                    self._process_long_opt(rargs, values)
                elif arg[:1] == "-" and len(arg) > 1:
                    if len(arg) > 2:
                        self._process_long_opt(rargs, values)
                    else:
                        self._process_short_opts(rargs, values)
                elif self.allow_interspersed_args:
                    largs.append(arg)
                    del rargs[0]
                else:
                    return 
    

    现在你可以做

    parser = MyOptionParser()
    parser.add_option(MyOption("-f", "-file", dest="filename",
                     help="write report to FILE", metavar="FILE"))
    parser.add_option(MyOption("-q", "-quiet",
                     action="store_false", dest="verbose", default=True,
                     help="don't print status messages to stdout"))
    

    这样,parser 将接受 -file 作为选项(并且不接受例如-fq)。

    【讨论】:

    • 非常感谢。这实际上对我有帮助。但是,当打印帮助或提到无效选项时,它会打印 -- 选项。要清楚。在您上面的代码中,如果我在命令行中将选项指定为 -fle,则错误消息将是:“没有这样的选项 --fle”。我在哪里可以更改此行为,以便将其打印为“没有这样的选项:-fle”?
    • 为此,您需要修补 Option。我已在答案中添加了必要的补丁。
    • 我知道这有助于在“选项”中使用单个 - 设置长选项,因此当它打印帮助消息时,它会使用单个 - 打印选项。但是针对无效选项显示的错误消息显示双破折号。例如:考虑您上面提到的选项。在命令行中,如果我给出一个选项“-invalid”(一个不存在的选项),它会打印一条错误消息“no such option --invalid”(这有双破折号,但我在命令中给出了一个破折号线)。我不明白它是如何将 cmd 行参数更改为双破折号的。
    • @user2242512:我更新了OptionParserOption 的补丁。确保您拥有新代码(我删除了将- 转换为-- 的行,因为修补后的Option 不再需要)。
    • 在看到您的回复之前,我有点想通了,但是“非常感谢”。这解决了我最初遇到的问题。
    猜你喜欢
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多