首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Argparse-如何指定默认的子命令

Argparse-如何指定默认的子命令
EN

Stack Overflow用户
提问于 2018-05-25 01:26:23
回答 2查看 0关注 0票数 0

我正在使用Python2.7的arg解析包为命令行工具编写一些选项解析逻辑。该工具应接受下列参数之一:

“打开”:打开一个函数。

“关闭”:关闭一个功能。

没有提供任何论据*回显函数的当前状态。

查看arg解析文档使我相信,我希望定义两个-可能是三个-子命令,因为这三个状态是相互排斥的,并且代表不同的概念活动。这是我目前对代码的尝试:

代码语言:txt
复制
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,如果我提供了一个参数,主解析器将使用适当的子命令的默认值并调用func=set_state。相反,我得到以下带有0参数的错误:

代码语言:txt
复制
usage: cvsSecure.py [-h] {ON,OFF} ...
cvsSecure.py: error: too few arguments

如果我提供“关闭”或“开启”,print_state获取调用而不是set_state.如果我评论一下parser.set_defaults线,set_state被正确调用。

我是一个熟练的程序员,但是Python的初级程序员。有什么建议可以让我这样做吗?

EN

回答 2

Stack Overflow用户

发布于 2018-05-25 09:38:04

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

代码语言:txt
复制
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。“选择”参数指定允许的选项,而将“Nargs”设置为“?”则指定如果可用,应使用1个参数,否则不应使用任何参数。

编辑:如果要添加带参数的强制命令,并为ON和OFF命令提供单独的帮助文本,则确实需要使用子命令。不幸的是,似乎没有指定默认子命令的方法。但是,可以通过检查空参数列表并提供自己的参数来解决这个问题。

代码语言:txt
复制
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)
票数 0
EN

Stack Overflow用户

发布于 2018-05-25 11:06:50

这应该解释为什么将默认的newstate两次将导致第一个值被覆盖。无论是否使用“ON”或“OFF”作为参数调用您的程序,每次set_state()将被调用OFF。如果你只想python cvsSecure ONpython cvsSecure OFF以下措施将起作用:

代码语言:txt
复制
from __future__ import print_function

import sys
import argparse

def set_state(state):
    print("set_state", state)

def do_on(args):
    set_state('ON')

def do_off(args):
    set_state('OFF')

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

parser_on = subparsers.add_parser('ON')
parser_on.set_defaults(func=do_on)
parser_on.add_argument('--fast', action='store_true')
parser_off = subparsers.add_parser('OFF')
parser_off.set_defaults(func=do_off)

args = parser.parse_args()
args.func(args)

第二个问题是argparse是否将子解析器作为单个值参数处理,因此必须在调用parser.parse_args()。可以通过添加额外的子解析器“print”并使用以下方法自动插入缺少的参数set_default_subparser加到argparse.ArgumentParser()

代码语言:txt
复制
from __future__ import print_function

import sys
import argparse

def set_default_subparser(self, name, args=None):
    """default subparser selection. Call after setup, just before parse_args()
    name: is the name of the subparser to call by default
    args: if set is the argument list handed to parse_args()

    , tested with 2.7, 3.2, 3.3, 3.4
    it works with 2.6 assuming argparse is installed
    """
    subparser_found = False
    for arg in sys.argv[1:]:
        if arg in ['-h', '--help']:  # global help if no subparser
            break
    else:
        for x in self._subparsers._actions:
            if not isinstance(x, argparse._SubParsersAction):
                continue
            for sp_name in x._name_parser_map.keys():
                if sp_name in sys.argv[1:]:
                    subparser_found = True
        if not subparser_found:
            # insert default in first position, this implies no
            # global options without a sub_parsers specified
            if args is None:
                sys.argv.insert(1, name)
            else:
                args.insert(0, name)

argparse.ArgumentParser.set_default_subparser = set_default_subparser


def print_state(args):
    print("print_state")

def set_state(state):
    print("set_state", state)

def do_on(args):
    set_state('ON')

def do_off(args):
    set_state('OFF')

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

parser_print = subparsers.add_parser('PRINT', help='default action')
parser_print.set_defaults(func=print_state)
parser_on = subparsers.add_parser('ON')
parser_on.set_defaults(func=do_on)
parser_on.add_argument('--fast', action='store_true')
parser_off = subparsers.add_parser('OFF')
parser_off.set_defaults(func=do_off)

parser.set_default_subparser('PRINT')

args = parser.parse_args()
args.func(args)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100008576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档