如何处理不能一起使用的选项(使用OptionParser)?

Joe*_*oel 7 python optparse

我的Python脚本(对于todo列表)是从命令行启动的,如下所示:

todo [options] <command> [command-options]
Run Code Online (Sandbox Code Playgroud)

例如,某些选项不能一起使用

todo add --pos=3 --end "Ask Stackoverflow"
Run Code Online (Sandbox Code Playgroud)

将指定列表的第三个位置和结尾.同样

todo list --brief --informative
Run Code Online (Sandbox Code Playgroud)

会使我的计划混淆是简短或内容丰富.由于我希望拥有相当强大的选项控制功能,因此像这样的情况将是一堆,未来肯定会出现新的情况.如果用户传递了错误的选项组合,我想提供一条信息性消息,最好还有optparse提供的使用帮助.目前我用if-else语句处理这个问题,我发现它真的很丑陋而且很差.我的梦想是在我的代码中有这样的东西:

parser.set_not_allowed(combination=["--pos", "--end"], 
                       message="--pos and --end can not be used together")
Run Code Online (Sandbox Code Playgroud)

并且OptionParser在解析选项时会使用它.

因为据我所知这不存在,我问SO社区:你如何处理这个问题?

Tam*_*más 6

可能通过扩展optparse.OptionParser:

class Conflict(object):
    __slots__ = ("combination", "message", "parser")

    def __init__(self, combination, message, parser):
        self.combination = combination
        self.message = str(message)
        self.parser = parser

    def accepts(self, options):
        count = sum(1 for option in self.combination if hasattr(options, option))
        return count <= 1

class ConflictError(Exception):
    def __init__(self, conflict):
        self.conflict = conflict

    def __str__(self):
        return self.conflict.message

class MyOptionParser(optparse.OptionParser):
    def __init__(self, *args, **kwds):
        optparse.OptionParser.__init__(self, *args, **kwds)
        self.conflicts = []

    def set_not_allowed(self, combination, message):
        self.conflicts.append(Conflict(combination, message, self))

    def parse_args(self, *args, **kwds):
        # Force-ignore the default values and parse the arguments first
        kwds2 = dict(kwds)
        kwds2["values"] = optparse.Values()
        options, _ = optparse.OptionParser.parse_args(self, *args, **kwds2)

        # Check for conflicts
        for conflict in self.conflicts:
            if not conflict.accepts(options):
                raise ConflictError(conflict)

        # Parse the arguments once again, now with defaults
        return optparse.OptionParser.parse_args(self, *args, **kwds)
Run Code Online (Sandbox Code Playgroud)

然后ConflictError,您可以处理您呼叫的位置parse_args:

try:
    options, args = parser.parse_args()
except ConflictError as err:
    parser.error(err.message)
Run Code Online (Sandbox Code Playgroud)