7

Python 2.7 的 argparse 为您提供了两个扩展点,您可以在其中控制命令行参数的解析方式:类型函数和操作类。

从内置类型和操作来看,最佳实践似乎是类型函数应该包含验证/初始化代码,并且操作应该关注将值存储到命名空间中。这种方法的问题是当您的类型检查代码具有副作用时。考虑这个简单的例子:

from argparse import ArgumentParser, FileType
argp = ArgumentParser()
argp.add_argument('-o', type=FileType('w'), default='myprog.out')
argp.parse_args(['-o', 'debug.out'])

如果你运行它,你会发现 python 会在系统上打开两个文件,myprog.out并且debug.out. debug.out仅在用户不提供-o参数时才打开会更有意义。

稍微戳了一下,似乎 argparse 只会在传递的参数或 str 类型的默认参数上调用您的类型函数。如果您的类型检查器有副作用,这是不幸的,因为即使传递了一个值,它也会在默认情况下被调用。所以对于有副作用的初始化,也许在action中做会更好。这样做的问题是,如果您提供默认值,则不会调用该操作!

考虑以下代码:

from argparse import ArgumentParser, Action

def mytype(arg):
    print 'checking type for ' + repr(arg)
    return arg

class OutputFileAction(Action):
    def __call__(self, parser, namespace, values, option_string=None):
        print 'running action for ' + repr(values)
        try:
            outstream = open(values, 'w')
        except IOError as e:
            raise ArgumentError('error opening file ' + values)
        setattr(namespace, self.dest, outstream)

argp = ArgumentParser()
argp.add_argument('-o', type=mytype, action=OutputFileAction, default='myprog.out')

现在尝试使用它:

>>> argp.parse_args([])
checking type for 'myprog.out'
Namespace(o='myprog.out')
>>> argp.parse_args(['-o', 'debug.out'])
checking type for 'myprog.out'
checking type for 'debug.out'
running action for 'debug.out'
Namespace(o=<open file 'debug.out', mode 'w' at 0x2b7fced07300>)

谁命令了这种行为?有没有一种理智的方法可以让默认值的行为与用户传入的完全一样?或者在提供值时不检查默认值?

4

1 回答 1

2

As far as I am aware, there is no "sensible" way to do this. Of course, it is trivial to leave the type conversion off and then postprocess the Namespace returned from parse_args:

args = argp.parse_args()
args.o = open(args.o,'w')

but I suppose that isn't what you're looking for.

于 2012-09-13T00:43:49.643 回答