9

argparseモジュールが大好きです。値を指定した場合でもデフォルトの出力ファイルが作成されるため、デフォルトargparse.FileTypeを他のものにしたい場合を除き、これも役立ちます。sys.std*

例えば:

parser.add_argument('--outfile', type=FileType('w'), default="out.txt")

--outfile でファイルを指定しても、out.txt が作成されます。

私が思いつくことができる最高のものは次のとおりです。

class MagicFileType(object):

    def __init__(self, *args, **kwargs):

        # save args/kwargs and set filetype to None
        self.filetype = None
        self.args = args
        self.kwargs = kwargs

    def __getattr__(self, attr):
        """ Delegate everything to the filetype """

        # If we haven't created it, now is the time to do so
        if self.filetype is None:
            self.filetype = FileType(*self.args, **self.kwargs)
            self.filetype = self.filetype(self.filename)

        return getattr(self.filetype, attr)

    def __call__(self, filename):
        """ Just cache the filename """

        # This is called when the default is created
        # Just cache the filename for now.
        self.filename = filename
        return self

しかし、これがもっと簡単なはずだと感じたら、何か足りないのでしょうか?

4

1 に答える 1

3

http://bugs.python.org/issue12776argparse (2012 年 8 月) に、デフォルト値の評価を遅らせる比較的最近の変更がありました。もともと、文字列のデフォルトは、解析の開始時に(経由で)渡され、その結果、FileType ファイルが開かれ (および作成され) (必要かどうかにかかわらず) ました。このパッチでは、文字列は名前空間に書き込まれますが、別の値が提供されたかどうかを判断できる解析の​​最後まで評価されません。基本的に、この行は初期から最後に移動されましたtype_get_valueparse_known_args_parse_known_args

default = self._get_value(action, action.default)

http://bugs.python.org/issue13824で、タイプを提供するパッチを提案しましたFileContext。との主な違いFileTypeは、 を でラップすることopen(file...)ですpartialwith args.output() as f:そうすれば、コンテキストで実際に使用されるまで、ファイルは開かれません (または作成されません) 。

このパッチは、ファイルを作成できるかどうかのテスト ( を使用os.access) や、ダミー コンテキストでのラップなど、他のいくつかのことを処理して、ファイルをstdin/out閉じようとしないようにします。

テストせずに、次のように変更できますFileType

class FileOpener(argparse.FileType):
    # delayed FileType;
    # sample use:
    # with args.input.open() as f: f.read()
    def __call__(self, string):
        # optionally test string
        self.filename = string
        return self
    def open(self):
        return super(FileOpener,self).__call__(self.filename)
    file =  property(open, None, None, 'open file property')
于 2013-09-27T21:07:46.693 に答える