4

このコマンドラインでプログラムを書く必要があります:

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: '-'

aまたはを試しr+ましたが、同じエラーが発生します。Windows で Python 2.7 を使用していますが、Linux でも動作する必要があります。コマンド ラインは、レガシー サポートのために変更できません。

argparsestdout 省略形の組み込みサポートを維持しながら、上書き機能をサポートするにはどうすればよいですか?

4

1 に答える 1

5

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!'
于 2013-05-03T18:35:08.467 に答える