python getopt argparse,可以Python的argparse permute参数顺序像gnu getopt?

GNU getopt, and command line tools that use it, allow options and arguments to be interleaved, known as permuting options (see http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html#Using-Getopt). Perl's Getopt::Long module also supports this (with qw(:config gnu_getopt)). argparse seems to not support (or even mention) permuting options.

There are many SO questions related to arg/opt order, but none seem answer this question: Can argparse be made to permute argument order like getopt?

The use case is a prototypical command line signature like GNU sort:

sort [opts] [files]

in which 1) options and files are permuted, and 2) the file list may contain zero or more arguments.

For example:

import argparse

p = argparse.ArgumentParser();

p.add_argument('files',nargs='*',default=['-']);

p.add_argument('-z',action='store_true')

p.parse_args(['-z','bar','foo']) # ok

p.parse_args(['bar','foo','-z']) # ok

p.parse_args(['bar','-z','foo']) # not okay

usage: ipython [-h] [-z] [files [files ...]]

I've tried:

p.parse_known_args -- doesn't complain, but doesn't actually permute either and it doesn't balk about arguments that look like invalid options (e.g., --bogus or -b above).

p.add_argument('files',nargs=argparse.REMAINDER) -- option -z is included in files unless before positional args

p.add_argument('files',nargs='*',action='append');

I want to implement something close to the GNU sort prototype above. I am not interested in a flag that can be specified for each file (e.g., -f file1 -f file2).

解决方案

Here's a quick solution which decodes the argument list one (options, positional arguments) pair at a time.

import argparse

class ExtendAction(argparse.Action):

def __call__(self, parser, namespace, values, option_string=None):

items = getattr(namespace, self.dest, None)

if items is None:

items = []

items.extend(values)

setattr(namespace, self.dest, items)

parser = argparse.ArgumentParser()

parser.add_argument('files', nargs='*', action=ExtendAction)

parser.add_argument('-z', action='store_true')

parser.add_argument('-v', action='count')

parser.add_argument('args_tail', nargs=argparse.REMAINDER)

def interleaved_parse(argv=None):

opts = parser.parse_args(argv)

optargs = opts.args_tail

while optargs:

opts = parser.parse_args(optargs, opts)

optargs = opts.args_tail

return opts

print(interleaved_parse('-z bar foo'.split()))

print(interleaved_parse('bar foo -z'.split()))

print(interleaved_parse('bar -z foo'.split()))

print(interleaved_parse('-v a -zv b -z c -vz d -v'.split()))

Output:

Namespace(args_tail=[], files=['bar', 'foo'], v=None, z=True)

Namespace(args_tail=[], files=['bar', 'foo'], v=None, z=True)

Namespace(args_tail=[], files=['bar', 'foo'], v=None, z=True)

Namespace(args_tail=[], files=['a', 'b', 'c', 'd'], v=4, z=True)

Note: Don't try to use this with other non-flag arguments (besides a single nargs='*' argument and the args_tail argument). The parser won't know about previous invocations of parse_args so it will store the wrong value for these non-flag arguments. As a workaround, you can parse the nargs='*' argument manually after using interleaved_parse.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值