Python标准模块--linecache

1.模块简介

linecache主要用于缓存文件内容,如果下次继续读取该文件,则不需要打开文件,直接在缓存中获取该文件内容。

2.模块使用

模块的基本方法有getline,clearcache,getlines,checkcache;

方法getline主要用于获取指定行的内容;

方法clearcache主要用于清空缓存;

方法getlines主要用于从缓存中获取文件所有的行,如果缓存中没有该文件内容,则更新缓存,如果更新缓存失败(例如文件太大),则返回空列表;

方法checkcache主要用于删除超时的缓存;

example,

import linecache
import os

# 小文件名称
smallFileName = "BrowseQueryResult.txt"
# 大文件名称
bigFileName = "PaperID_mapping_to_AffiliationsID.txt"

# 获取小文件第一行
samllLine1 = linecache.getline(smallFileName,1)
print "small file line 1:" + samllLine1.decode("gb2312")
# 获取小文件所有数据
cacheSmall = linecache.getlines(smallFileName)
print "samll file length = %d"%(len(cacheSmall))
print "small file size = %d KB"%(os.path.getsize(smallFileName) * 1.0 / (1024))

# 获取大文件所有数据
cacheBig = linecache.getlines(bigFileName)
print "big file length = %d"%(len(cacheBig))
print "big file size = %d MB"%(os.path.getsize(bigFileName) * 1.0 / ( 1024* 1024))

linecache.clearcache()

控制台输出,可以发现,当系统配置低的时候,linecache.getlines获取大文件时,会失败,这时候得到的是一个空列表,通过os.path.getsize可以观察到文件的大小。

small file line 1:教育技术学视野下的未来课堂研究        1769    教育|199||教育技术|53||教育技术学|22||未来课堂|13||技术|12||教育技术学视野下的未来课堂研究|7||课堂教学模式|5||云计算|5||教学模式|5||课堂
|5||发展性教学|4||信息化教学模式|4||教育技术 并含 技能|4||颠倒课堂|4||课堂教学|4||在线教育|4||未来教室|4||课堂互动|4||计算机|3||思维导图|3||智慧教室|3||信息化教学|3||教育技术 技能|3||教育技术学视野下
的未来课堂|3||毕业论文|3||电子书包|3||合作学习|2||互联网|2||评价|2||提高远程教学交互实效的教学教法研究|2||教育技术研究方法|2||沉积物磷|2||数学 自主探究|2||教育技术技能|2||学习空间设计|2||教育技术发展|
2||电子商务|2||数字化校园|2||信息技术支持下的教育教学模式研究|2||情报 技术|2||末来课堂|2||模糊数学|2||绿色建筑|2||数学|2||心理学|2||物流|2||泛在学习|2||财务管理|2||未来|2||信息技术|2

samll file length = 100
small file size = 103 KB
big file length = 0
big file size = 3219 MB

3.源码分析

linecache源码所在路径为Python-2.7.10Liblinecache.py,

源码如下,

"""Cache lines from files.

This is intended to read lines from modules imported -- hence if a filename
is not found, it will look down the module search path for a file by
that name.
"""

import sys
import os

__all__ = ["getline", "clearcache", "checkcache"]

# 获取指定行的内容
def getline(filename, lineno, module_globals=None):
    # 利用getlines获取所有行
    lines = getlines(filename, module_globals)
    # 如果指定行在文件总行数范围之内,则返回相应的该行的数据
    if 1 <= lineno <= len(lines):
        return lines[lineno-1]
    else:
        return ''


# cache的数据格式为cache[filename] = size, mtime, lines, fullname
# filename为文件名
# size为文件大小
# mtime为文件修改时间
# lines为文件所有的数据
# fullname为文件的全名
cache = {} # The cache


# 清空缓存
def clearcache():
    """Clear the cache entirely."""
    # 引入全局变量cache
    global cache
    # 将cache设置为空
    cache = {}


# 从缓存中获取文件所有的行,如果缓存中没有该文件内容,则更新缓存,如果更新缓存失败(例如文件太大),则返回空列表
def getlines(filename, module_globals=None):
    """Get the lines for a file from the cache.
    Update the cache if it doesn't contain an entry for this file already."""

    # 如果文件名在cache中,则返回cache中该文件的全部数据
    if filename in cache:
        return cache[filename][2]

    # 否则,更新cache
    try:
        return updatecache(filename, module_globals)
    # 如果更新cache时,发生内存错误,则返回空列表
    except MemoryError:
        clearcache()
        return []


# 删除超时的缓存cache
def checkcache(filename=None):
    """Discard cache entries that are out of date.
    (This is not checked upon each call!)"""

    if filename is None:
        filenames = cache.keys()
    else:
        if filename in cache:
            filenames = [filename]
        else:
            return

    for filename in filenames:
        size, mtime, lines, fullname = cache[filename]
        if mtime is None:
            continue   # no-op for files loaded via a __loader__
        # 获取cache中文件的修改时间
        try:
            stat = os.stat(fullname)
        # auguries出错,则将cache中的该文件内容删除
        except os.error:
            del cache[filename]
            continue
        # 如果文件大小和修改时间均不相等,则将cache中的该文件内容删除
        if size != stat.st_size or mtime != stat.st_mtime:
            del cache[filename]

# 更新缓存
def updatecache(filename, module_globals=None):
    """Update a cache entry and return its list of lines.
    If something's wrong, print a message, discard the cache entry,
    and return an empty list."""

    # 如果文件名在缓存cache中,将cache中的该文件内容删除
    if filename in cache:
        del cache[filename]
    # 如果文件名不合法,则返回空列表
    if not filename or (filename.startswith('<') and filename.endswith('>')):
        return []

    # 将文件名设置为文件名全称
    fullname = filename
    # 获取该文件名全称的状态
    try:
        stat = os.stat(fullname)
    # 如果出错,则将文件名设置为基本文件名
    except OSError:
        basename = filename

        # Try for a __loader__, if available
        if module_globals and '__loader__' in module_globals:
            name = module_globals.get('__name__')
            loader = module_globals['__loader__']
            get_source = getattr(loader, 'get_source', None)

            if name and get_source:
                try:
                    data = get_source(name)
                except (ImportError, IOError):
                    pass
                else:
                    if data is None:
                        # No luck, the PEP302 loader cannot find the source
                        # for this module.
                        return []
                    cache[filename] = (
                        len(data), None,
                        [line+'
' for line in data.splitlines()], fullname
                    )
                    return cache[filename][2]

        # Try looking through the module search path, which is only useful
        # when handling a relative filename.
        if os.path.isabs(filename):
            return []

        # 从系统路径中获取目录路径
        for dirname in sys.path:
            # When using imputil, sys.path may contain things other than
            # strings; ignore them when it happens.
            try:
                fullname = os.path.join(dirname, basename)
            except (TypeError, AttributeError):
                # Not sufficiently string-like to do anything useful with.
                continue
            try:
                stat = os.stat(fullname)
                break
            except os.error:
                pass
        else:
            return []
    # 通过file.readlines()读取文件的所有内容
    try:
        with open(fullname, 'rU') as fp:
            lines = fp.readlines()
    # 读取失败,则返回空列表
    except IOError:
        return []
    if lines and not lines[-1].endswith('
'):
        lines[-1] += '
'
    size, mtime = stat.st_size, stat.st_mtime
    # 以filename为key,(size, mtime, lines, fullname)为value
    cache[filename] = size, mtime, lines, fullname
    return lines
原文地址:https://www.cnblogs.com/zhbzz2007/p/5957644.html