python类文件上下文管理器

时间:2015-06-05 17:47:06

标签: python with-statement

我正在尝试在类中打开一个文件,并以这种方式在退出时关闭它。

class PlanetaryImage(object):
    @classmethod
    def open(cls, filename):
        with open(filename, 'rb') as fp:
            return cls(fp, filename)

    def __init__(self, stream, filename=None, memory_layout='DISK'):
        self.filename = filename
        self._parse_data(stream)

    def _parse_data(self, stream):
        data_stream = stream
        try:
            if self.data_filename is not None:
                dirpath = os.path.dirname(self.filename)
                data_file = os.path.abspath(
                    os.path.join(dirpath, self.data_filename))

                data_stream = open(data_file, 'rb')

            data_stream.seek(self.start_byte)
            if self.format in self.BAND_STORAGE_TYPE:
                return getattr(self, self.BAND_STORAGE_TYPE[self.format])(data_stream)

            raise Exception('Unkown format (%s)' % self.format)

        finally:
            data_stream.close()

在某些情况下,我必须在_parse_data函数中再使用一个文件。我想使用with,但if语句使其变得困难。关于如何使try部分更加pythonic的任何建议。

1 个答案:

答案 0 :(得分:0)

_parse_data没有理由尝试打开文件。调用者有责任将PlanetaryImage.open与文件名一起使用,或者为__init__提供打开的文件句柄。 _parse_data应该只做一件事:解析其流参数中的数据。

class PlanetaryImage(object):
    @classmethod
    def open(cls, filename):
        with open(filename, 'rb') as fp:
            return cls(fp, filename)

    def __init__(self, stream, memory_layout='DISK'):
        self._parse_data(stream)

    def _parse_data(self, data_stream):
        try:        
            data_stream.seek(self.start_byte)
            if self.format in self.BAND_STORAGE_TYPE:
                return getattr(self, self.BAND_STORAGE_TYPE[self.format])(data_stream)

            raise Exception('Unkown format (%s)' % self.format)

        finally:
            data_stream.close()

现在,使用该类只有两个选项:

with open(filename, 'rb') as fp:
    x = PlanetaryImage(fp)
    ...

x = PlanetaryImage(filename)
....