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