Python argparse - 使用子解析器和父解析器时命令解析不正确

1 投票
1 回答
1325 浏览
提问于 2025-04-17 18:47

在我的应用程序中,我有一个解析器,像这样:

description = ("Cluster a matrix using bootstrap resampling or "
               "Bayesian hierarchical clustering.")
sub_description = ("Use these commands to cluster data depending on "
                   "the algorithm.")

parser = argparse.ArgumentParser(description=description, add_help=False)
subparsers = parser.add_subparsers(title="Sub-commands",
                                   description=sub_description)
parser.add_argument("--no-logfile", action="store_true", default=False,
                    help="Don't log to file, use stdout")
parser.add_argument("source", metavar="FILE",
                    help="Source data to cluster")
parser.add_argument("destination", metavar="FILE",
                     help="File name for clustering results")

然后我添加了一系列子解析器,像这样(因为它们比较长,所以用函数来处理):

setup_pvclust_parser(subparsers, parser)
setup_native_parser(subparsers, parser)

这些子解析器会调用(这里举个例子):

def setup_pvclust_parser(subparser, parent=None):

    pvclust_description = ("Perform multiscale bootstrap resampling "
                           "(Shimodaira et al., 2002)")
    pvclust_commands = subparser.add_parser("bootstrap",
        description=pvclust_description, parents=[parent])
     pvclust_commands.add_argument("-b", "--boot", type=int,
                                   metavar="BOOT",
                                   help="Number of permutations",
                                   default=100)

    # Other long list of options...

    pvclust_commands.set_defaults(func=cluster_pvclust) # The function doing the processing

问题是,命令行的解析 somehow 失败了,我确信这是我某个地方搞错了。比如运行时的情况:

  my_program.py bootstrap --boot 10 --no-logfile test.txt test.pdf

  my_program.py bootstrap: error: too few arguments

就好像解析的过程有问题一样。如果我在子解析器调用中去掉 parents=[],这个问题就消失了,但我不想这样做,因为那样会造成大量重复。

编辑:把 subparsers 的调用放在 add_argument 调用之后,解决了部分问题。然而,现在解析器无法正确解析子命令:

my_program.py bootstrap --boot 100 --no-logfile test.txt test.pdf

my_program.py: error: invalid choice: 'test.txt' (choose from 'bootstrap', 'native')

1 个回答

3

根本的问题是,你把parser应该处理的参数和子解析器(subparsers)应该处理的参数搞混了。实际上,把解析器作为子解析器的父级传递过去,结果就是在两个地方都定义了这些参数。

另外,sourcedestination是位置参数,子解析器也是。如果它们都在基础解析器中定义,那么它们的顺序就很重要。

我建议你定义一个单独的parent解析器。

parent = argparse.ArgumentParser(add_help=False)
parent.add_argument("--no-logfile", action="store_true". help="...")
parent.add_argument("source", metavar="FILE", help="...")
parent.add_argument("destination", metavar="FILE", help="...")

parser = argparse.ArgumentParser(description=description)
subparsers = parser.add_subparsers(title="Sub-commands", description=sub_description)
setup_pvclust_parser(subparsers, parent)
setup_native_parser(subparsers, parent)

撰写回答