将 argparse 与安装工具入口点结合使用

sie*_*z0r 5 python setuptools python-2.7 argparse

我正在编写一个脚本,我想使用安装工具分发该脚本。我已将此脚本添加到entry_points我的setup.py.

从安装工具文档:

您指定的函数在不带参数的情况下调用,它们的返回值将传递给 sys.exit(),因此您可以返回错误级别或消息以打印到 stderr

由于该方法将返回而不是退出,因此它变得更易于测试。出于可测试性的目的,我接受方法中默认为sys.argv. 到目前为止,一切都很好。

当 argparse 添加到混合中时,问题就出现了。当 argparse 无法解析 args 时,它会调用sys.exit. 现在我真的更希望 argparse 不这样做,因为这是由 setuptools 包装器处理的。我能想到解决这个问题的第一件事就是覆盖,argparse.ArgumentParser但后来我看到了这个:

# ===============
# Exiting methods
# ===============
def exit(self, status=0, message=None):
    if message:
        self._print_message(message, _sys.stderr)
    _sys.exit(status)

def error(self, message):
    """error(message: string)

    Prints a usage message incorporating the message to stderr and
    exits.

    If you override this in a subclass, it should not return -- it
    should either exit or raise an exception.
    """
    self.print_usage(_sys.stderr)
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
Run Code Online (Sandbox Code Playgroud)

所以文档字符串指出我不应该返回并坚持引发异常。我应该如何解决这个问题?

主要方法如果我解释得不够彻底的话:

def main(args=sys.argv):
    parser = ArgumentParser(prog='spam')

    # parser is configured here

    parsed = parser.parse_args(args)

    # Parsed args are used here
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 2

您不想这样return做的原因error是解析器将继续解析。一些错误是在接近结束时引发的(例如,关于未解析的字符串),但其他错误可能会提前发生(例如,第一个参数字符串的类型错误)。parse_args如果您从错误方法返回,则的行为是不可预测的。通常您希望解析器退出并返回代码的控制权。

您想要做的是将调用parse_args()包装在一个try: except SystemExit:块中。我经常使用这样的测试脚本:

for test in ['-o FILE',
    ...
         ]:
    print(test)
    try:
        print(parser.parse_args(test.split()))
    except SystemExit:
        pass
Run Code Online (Sandbox Code Playgroud)

您可以使用error和/或exit返回其他类型的异常。他们还可以绕过使用消息。但以某种方式,您需要将异常捕获在包装器中。