Argparse - 如何指定默认子命令 [英] Argparse - How to Specify a Default Subcommand

查看:27
本文介绍了Argparse - 如何指定默认子命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Python 2.7 的 argparse 包为命令行工具编写一些选项解析逻辑.该工具应接受以下参数之一:

I am using the argparse package of Python 2.7 to write some option-parsing logic for a command-line tool. The tool should accept one of the following arguments:

ON":打开一个功能.
OFF":关闭功能.
[未提供参数]:回显函数的当前状态.

"ON": Turn a function on.
"OFF": Turn a function off.
[No arguments provided]: Echo the current state of the function.

查看 argparse 文档让我相信我想要定义两个——可能是三个——子命令,因为这三个状态是相互排斥的,代表不同的概念活动.这是我目前对代码的尝试:

Looking at the argparse documentation led me to believe that I wanted two--possibly three--subcommands to be defined, since these three states are mutually exclusive and represent different conceptual activities. This is my current attempt at the code:

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.set_defaults(func=print_state) # I think this line is wrong.

parser_on = subparsers.add_parser('ON')
parser_on.set_defaults(func=set_state, newstate='ON')

parser_off = subparsers.add_parser('OFF')
parser_off.set_defaults(func=set_state, newstate='OFF')

args = parser.parse_args()

if(args.func == set_state):
    set_state(args.newstate)
elif(args.func == print_state):
    print_state()
else:
    args.func() # Catchall in case I add more functions later

我的印象是,如果我提供 0 个参数,主解析器将设置 func=print_state,如果我提供 1 个参数,主解析器将使用适当的子命令的默认值并调用 <代码>func=set_state.相反,我收到以下带有 0 个参数的错误:

I was under the impression that if I provided 0 arguments, the main parser would set func=print_state, and if I provided 1 argument, the main parser would use the appropriate subcommand's defaults and call func=set_state. Instead, I get the following error with 0 arguments:

usage: cvsSecure.py [-h] {ON,OFF} ...
cvsSecure.py: error: too few arguments

如果我提供OFF"或ON",将调用 print_state 而不是 set_state.如果我注释掉 parser.set_defaults 行,set_state 就会被正确调用.

And if I provide "OFF" or "ON", print_state gets called instead of set_state. If I comment out the parser.set_defaults line, set_state is called correctly.

我是一名熟练工级别的程序员,但我是 Python 的初级初学者.关于如何使这项工作正常工作的任何建议?

I'm a journeyman-level programmer, but a rank beginner to Python. Any suggestions about how I can get this working?

编辑:我查看子命令的另一个原因是我正在考虑未来的第四个潜在功能:

Edit: Another reason I was looking at subcommands was a potential fourth function that I am considering for the future:

"FORCE txtval":设置函数的状态为txtval.

"FORCE txtval": Set the function's state to txtval.

推荐答案

顶级解析器的默认值覆盖了子解析器的默认值,因此设置 func 的默认值在子解析器被忽略,但子解析器默认值中的 newstate 值是正确的.

The defaults of the top-level parser override the defaults on the sub-parsers, so setting the default value of func on the sub-parsers is ignored, but the value of newstate from the sub-parser defaults is correct.

我认为您不想使用子命令.当可用选项和位置参数根据选择的子命令而改变时,将使用子命令.但是,您没有其他选项或位置参数.

I don't think you want to use subcommands. Subcommands are used when the available options and positional arguments change depending on which subcommand is chosen. However, you have no other options or positional arguments.

以下代码似乎可以满足您的要求:

The following code seems to do what you require:

import argparse

def print_state():
    print "Print state"

def set_state(s):
    print "Setting state to " + s

parser = argparse.ArgumentParser()
parser.add_argument('state', choices = ['ON', 'OFF'], nargs='?')

args = parser.parse_args()

if args.state is None:
    print_state()
elif args.state in ('ON', 'OFF'):
    set_state(args.state)

注意parser.add_argument 的可选参数.choices"参数指定允许的选项,同时将nargs"设置为?"指定如果可用,则应使用 1 个参数,否则不应使用任何参数.

Note the optional parameters to parser.add_argument. The "choices" parameter specifies the allowable options, while setting "nargs" to "?" specifies that 1 argument should be consumed if available, otherwise none should be consumed.

如果你想添加一个带有参数的 FORCE 命令并且有单独的 ON 和 OFF 命令的帮助文本,那么你确实需要使用子命令.不幸的是,似乎没有指定默认子命令的方法.但是,您可以通过检查空参数列表并提供您自己的参数列表来解决该问题.下面是一些示例代码,说明了我的意思:

If you want to add a FORCE command with an argument and have separate help text for the ON and OFF command then you do need to use subcommands. Unfortunately there doesn't seem to be a way of specifying a default subcommand. However, you can work around the problem by checking for an empty argument list and supplying your own. Here's some sample code illustrating what I mean:

import argparse
import sys

def print_state(ignored):
    print "Print state"

def set_state(s):
    print "Setting state to " + s

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
on = subparsers.add_parser('ON', help = 'On help here.')
on.set_defaults(func = set_state, newstate = 'ON')
off = subparsers.add_parser('OFF', help = 'Off help here.')
off.set_defaults(func = set_state, newstate = 'OFF')
prt = subparsers.add_parser('PRINT')
prt.set_defaults(func = print_state, newstate = 'N/A')
force = subparsers.add_parser('FORCE' , help = 'Force help here.')
force.add_argument('newstate', choices = [ 'ON', 'OFF' ])
force.set_defaults(func = set_state)

if (len(sys.argv) < 2):
    args = parser.parse_args(['PRINT'])
else:
    args = parser.parse_args(sys.argv[1:])

args.func(args.newstate)

这篇关于Argparse - 如何指定默认子命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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