3

我正在使用 Argparser 来处理我的 CLI prog 的参数。但随着时间的推移,我认为使用它不是一个好主意。问题来了。我想使用没有任何前缀字符的选项。像git commitsvn move。我搜索了一下,发现 Argparse 有一个 add_subparser() 方法。让我们填充我们的foo prog:

parser = argparse.ArgumentParser(prog='foo', usage='%(prog)s [options]')

subparsers = parser.add_subparsers(help='sub-command help')
parser_a = subparsers.add_parser('add', help='a help')
parser_a.add_argument('-ap', '--add-project',
                    nargs='*',
                    action='store',
                    help="Add project")

parser_d = subparsers.add_parser('del', help='a help')
parser_d.add_argument('-dp', '--delete-project',
                    nargs='*',
                    action='store',
                    help="Delete project")

args = parser.parser_args()

现在让使用选项执行 foo 并打印args命名空间(我没有过去整个代码,你明白了):

$ ./foo del
Namespace(delete_project=None)
$ ./foo add
Namespace(add_project=None)

如您所见,如果我执行 option deladd_project不会传递给 variable args。如果我的 main() 函数中有一个“if 子句”,这会导致问题,例如

def main(args):

   if args.delete_project:
      ...
   if args.add_project:
      ...

我会得到一个AttributeError异常,如果我执行,命名空间没有名为add_project./foo del的属性。除此之外,我无法将任何参数传递给 optionsdeladd. 我还将 prefix_chars 设置为一个空字符串,这也不起作用。

有什么办法处理它?argparse 是否能够创建 git、svn 等选项。或者我应该创建自己的函数并自己处理所有参数?

4

2 回答 2

0

argparse 文档不推荐您的 if 语句,而是推荐如下内容:

parser_X.set_defaults(action=action_func)
args.action(args)

然后add_action 会查看add_project,del_action 会查看del_project。

于 2010-12-06T21:03:03.290 回答
0

编辑:显然默认为defaultis None,这意味着我们没有,所以你必须使用Trueand False(无论如何这是正确的方式)。

default当您将参数添加到解析器时,您需要添加:

parser_a.add_argument('-ap', '--add-project',
                    nargs = '*',
                    action = 'store_true',
                    default = False,
                    help = "Add project")

您可以在此处查看该add_argument方法的文档。(我意识到文档布局不是最有利于弄清楚如何做示例中没有提到的事情)argparse

此外,正如 Tobu 在他的回答中恰当地指出的那样,未使用的子解析器不会被调用,因此如果不至少保护代码try:块中的代码,就无法安全地探测它们的值。但是,实际上您应该使用将 anaction与子解析器关联的功能,除非您有更复杂的情况需要它们共享状态。

于 2010-12-06T21:01:40.950 回答