我必须指定什么模式来argparse.要追加的文件类型,保留-作为默认值



我必须用这个命令行写一个程序:

demo.py [-h] -f FILENAME [-o]

文件名是强制性的,意味着我们要附加到的文件。-o标志表示文件将被覆盖。

这个argparse代码几乎可以工作:

import argparse
parser = argparse.ArgumentParser(description='A foo that bars')
parser.add_argument("-f",
                  "--file", dest="filename", required=True,
                  type=argparse.FileType('a+'),
                  help="The output file (append mode, see --overwrite).")
parser.add_argument("-o",
                  "--overwrite", dest="overwrite",
                  action='store_true',
                  help="Will overwrite the filename if it exists")
args = parser.parse_args()
if args.overwrite:
    args.filename.truncate(0)
print >> args.filename, 'Hello, World!'

但是如果我指定- (stdout)作为文件名,我得到这个错误:

error: argument -f/--file: invalid FileType('a+') value: '-'

我尝试ar+,我得到同样的错误。我在Windows上使用Python 2.7,但它也必须在Linux上工作。命令行不能更改以获得旧版支持。

如何保持argparse内置支持标准输出速记,但支持覆盖功能?

argparse.FileType.__call__包含以下代码:

    if string == '-':
        if 'r' in self._mode:
            return _sys.stdin
        elif 'w' in self._mode:
            return _sys.stdout
        else:
            msg = _('argument "-" with mode %r') % self._mode
            raise ValueError(msg)

所以,如果self._mode'a+', Python会抛出ValueError。您可以通过子类化argparse.FileType:

来解决这个问题。
import argparse
import sys as _sys
class MyFileType(argparse.FileType):
    def __call__(self, string):
        # the special argument "-" means sys.std{in,out}
        if string == '-':
            if 'r' in self._mode:
                return _sys.stdin
            elif any(m in self._mode for m in 'wa'):
                return _sys.stdout
            else:
                msg = _('argument "-" with mode %r') % self._mode
                raise ValueError(msg)
        # all other arguments are used as file names
        try:
            return open(string, self._mode, self._bufsize)
        except IOError as e:
            message = _("can't open '%s': %s")
            raise ArgumentTypeError(message % (string, e))

def parse_options():
    parser = argparse.ArgumentParser(description='A foo that bars')
    parser.add_argument("-f",
                      "--file", dest="filename", required=True,
                      type=MyFileType('a+'),
                      help="The output file (append mode, see --overwrite).")
    parser.add_argument("-o",
                      "--overwrite", dest="overwrite",
                      action='store_true',
                      help="Will overwrite the filename if it exists")
    args = parser.parse_args()
    if args.overwrite:
        args.filename.truncate(0)
    return args
args = parse_options()
print >> args.filename, 'Hello, World!'

最新更新