django.core-files


首先看FileProxyMixin的定義:python

class FileProxyMixin(object):

    encoding = property(lambda self: self.file.encoding)
    fileno = property(lambda self: self.file.fileno)
    flush = property(lambda self: self.file.flush)
    isatty = property(lambda self: self.file.isatty)
    newlines = property(lambda self: self.file.newlines)
    read = property(lambda self: self.file.read)
    readinto = property(lambda self: self.file.readinto)
    readline = property(lambda self: self.file.readline)
    readlines = property(lambda self: self.file.readlines)
    seek = property(lambda self: self.file.seek)
    softspace = property(lambda self: self.file.softspace)
    tell = property(lambda self: self.file.tell)
    truncate = property(lambda self: self.file.truncate)
    write = property(lambda self: self.file.write)
    writelines = property(lambda self: self.file.writelines)
    xreadlines = property(lambda self: self.file.xreadlines)

    def __iter__(self):
        return iter(self.file)


能夠看到使用property屬性裝飾器和lambda函數,完成對self.file大部分操做的代理,而且也實現__iter__方法,支持迭代。函數

而後看File的定義,它的做用主要是完成對不一樣的類型的文件的抽象。增長chunks方法,用於分片讀取數據大的文件,增長closed的屬性,判斷是否文件關閉, 增長size屬性。this


首先看size屬性的實現函數:spa

def _get_size_from_underlying_file(self):
        if hasattr(self.file, 'size'):
            return self.file.size
        if hasattr(self.file, 'name'):
            try:
                return os.path.getsize(self.file.name)
            except (OSError, TypeError):
                pass
        if hasattr(self.file, 'tell') and hasattr(self.file, 'seek'):
            pos = self.file.tell()
            self.file.seek(0, os.SEEK_END)
            size = self.file.tell()
            self.file.seek(pos)
            return size
        raise AttributeError("Unable to determine the file's size.")


首先嚐試獲取self.file的size屬性, 而後嘗試獲取本地文件的大小,最後使用seek方法獲取大小。代理

self.file.seek(0, os.SEEK_END)
size = self.file.tell()


接下來看看File如何支持迭代的:code

def __iter__(self):
        # Iterate over this file-like object by newlines
        buffer_ = None
        for chunk in self.chunks():
            for line in chunk.splitlines(True):
                if buffer_:
                    if endswith_cr(buffer_) and not equals_lf(line):
                        # Line split after a \r newline; yield buffer_.
                        yield buffer_
                        # Continue with line.
                    else:
                        # Line either split without a newline (line
                        # continues after buffer_) or with \r\n
                        # newline (line == b'\n').
                        line = buffer_ + line
                    # buffer_ handled, clear it.
                    buffer_ = None

                # If this is the end of a \n or \r\n line, yield.
                if endswith_lf(line):
                    yield line
                else:
                    buffer_ = line

        if buffer_ is not None:
            yield buffer_

這裏迭代的邏輯,主要是buffer_的使用。get

首先會調用chunks進行塊讀取,而後將line進行分行(splitlines)。將每段line剩下的字節,保存在buffer_中,等待下段一塊兒合併。it

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息