argparse 可选位置参数和子解析器参数 [英] argparse optional positional argument and subparsers arguments

查看:21
本文介绍了argparse 可选位置参数和子解析器参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 python 脚本,它接受一个可选的位置参数并有几个子命令.其中一些子命令需要位置参数,有些不需要.当我尝试使用不需要位置参数的子命令时,我遇到的问题出现了.考虑以下测试文件:

I have a python script that takes in an optional positional argument and has a few subcommands. Some of these subcommands require the positional argument, some don't. The problem I have appears when I try to use a subcommand that does not require the positional argument. Consider the following test file:

import argparse

argp = argparse.ArgumentParser()
argp.add_argument('inputfile', type=str, nargs='?',
                  help='input file to process')
argp.add_argument('--main_opt1', type=str,
                  help='global option')

subp = argp.add_subparsers(title='subcommands',
                           dest='parser_name',
                           help='additional help',
                           metavar="<command>")

tmpp = subp.add_parser('command1', help='command1 help')
tmpp.add_argument('pos_arg1', type=str,
                  help='positional argument')

print repr(argp.parse_args())

当我尝试将子命令 <​​code>command1 与第一个参数一起使用时,一切顺利.

When I try to use the subcommand command1 with the first argument everything goes well.

macbook-pro:~ jmlopez$ python pytest.py filename command1 otherarg
Namespace(inputfile='filename', main_opt1=None, parser_name='command1', pos_arg1='otherarg')

但现在让我们假设 command1 不需要第一个位置参数.

But now let us assume that command1 doesn't need the first positional argument.

macbook-pro:~ jmlopez$ python pytest.py command1 otherarg
usage: pytest.py [-h] [--main_opt1 MAIN_OPT1] [inputfile] <command> ...
pytest.py: error: argument <command>: invalid choice: 'otherarg' (choose from 'command1')

我以某种方式期望将 inputfile 设置为 None.argparse 有什么办法可以预测 command1 实际上是一个子命令,因此 inputfile 应该设置为 None 吗?

I was somehow expecting inputfile to be set to None. Is there any way that argparse can predict that command1 is actually a subcommand and thus inputfile should be set to None?

推荐答案

对于 argp 来说,subparser 参数看起来就像另一个位置参数,一个需要选择(子解析器的名称).另外argppos_arg1 一无所知.这在 tmpp 的参数列表中.

To argp the subparser argument looks just like another positional, one that takes choices (the names of the subparsers). Also argp knows nothing about pos_arg1. That's in tmpp's list of arguments.

argp 看到filename command1 otherarg 时,filenamecommand1 满足它的2 个位置.otherarg 然后在 tmpp 上传递.

When argp sees filename command1 otherarg, filename and command1 satisfy its 2 positionals. otherarg is then passed on the tmpp.

使用 command1 otherarg,同样是 2 个字符串,2 个 argp 位置.command 被分配给 inputfile.没有逻辑可以回溯并说 command1 更适合 subcommands,或者 `tmpp' 需要这些字符串之一.

With command1 otherarg, again 2 strings, 2 argp positionals. command is assigned to inputfile. There's no logic to backtrack and say command1 fits subcommands better, or that `tmpp' needs one of those strings.

您可以将第一个位置更改为可选的 --inputfile.

You could change the 1st positional to an optional, --inputfile.

或者你可以inputfile另一个位置tmpp.如果许多子解析器需要它,请考虑使用 parents.

Or you could inputfile another positional of tmpp. If a number of the subparsers need it it, consider using parents.

argparse 不像你那么聪明,不能超前思考"或回溯".如果它看起来很聪明,那是因为它使用 re 模式匹配来处理 nargs 值(例如?、*、+).

argparse isn't a smart as you, and can't 'think ahead' or 'backtrack'. If it appears to do something smart it's because it uses re pattern matching to handle nargs values (e.g. ?, *, +).

编辑

欺骗"argparse 将第一个位置识别为子解析器的一种方法是在它之后插入一个可选的.使用 command1 -b xxx otherarg-b xxx 分解位置字符串列表,因此只有 command1inputfile<匹配/code> 和 子命令.

One way to 'trick' argparse into recognizing the first positional as the subparser is to insert an optional after it. With command1 -b xxx otherarg, -b xxx breaks up the list of positional strings, so only command1 is matched against inputfile and subcommands.

p=argparse.ArgumentParser()
p.add_argument('file',nargs='?',default='foo')
sp = p.add_subparsers(dest='cmd')
spp = sp.add_parser('cmd1')
spp.add_argument('subfile')
spp.add_argument('-b')

p.parse_args('cmd1 -b x three'.split())
# Namespace(b='x', cmd='cmd1', file='foo', subfile='three')

这里的问题是 argparse 如何处理带有变量 nargs 的 postionals.第二个位置是子解析器这一事实并不重要.虽然 argparse 允许任何顺序的可变长度位置,但它如何处理它们可能会令人困惑.如果只有一个这样的位置,则更容易预测 argparse 会做什么,并且它发生在最后.

The issue here is how argparse handles postionals with variable nargs. The fact that the 2nd positional is a subparser is not important. While argparse allows variable length positionals in any order, how it handles them can be confusing. It's easier to predict what argparse will do if there is only one such positional, and it occurs at the end.

这篇关于argparse 可选位置参数和子解析器参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆