Python3标准库:linecache高效读取文本文件

1. linecache高效读取文本文件

处理Python源文件时,在Python标准库的其他部分中用到了linecache模块。缓存实现将在内存中保存文件的内容(解析为单独的行)。这个API通过索引一个list来返回请求的行,与反复的读取文件并解析文本来查找所需文本行相比,这样可以节省时间。这个模块在查找同一个文件中的多行时尤其有用,比如为一个错误报告生成一个跟踪记录(traceback)。

1.1 测试数据

公共数据如下:

import os
import tempfile
import linecache

lorem = '''Lorem ipsum dolor sit amet, consectetuer
adipiscing elit.  Vivamus eget elit. In posuere mi non
risus. Mauris id quam posuere lectus sollicitudin
varius. Praesent at mi. Nunc eu velit. Sed augue massa,
fermentum id, nonummy a, nonummy sit amet, ligula. Curabitur
eros pede, egestas at, ultricies ac, apellentesque eu,
tellus.

Sed sed odio sed mi luctus mollis. Integer et nulla ac augue
convallis accumsan. Ut felis. Donec lectus sapien, elementum
nec, condimentum ac, interdum non, tellus. Aenean viverra,
mauris vehicula semper porttitor, ipsum odio consectetuer
lorem, ac imperdiet eros odio a sapien. Nulla mauris tellus,
aliquam non, egestas a, nonummy et, erat. Vivamus sagittis
porttitor eros.'''

def make_tempfile():
    fd, temp_file_name = tempfile.mkstemp()
    os.close(fd)
    with open(temp_file_name, 'wt') as f:
        f.write(lorem)
    return temp_file_name

def cleanup(filename):
    os.unlink(filename)

filename = make_tempfile()

1.2 读取特定行

linecache模块读取的文件行好从1开始,不过通常列表的数组索引会从0开始。

# Pick out the same line from source and cache.
# (Notice that linecache counts from 1)
print('SOURCE:')
print('{!r}'.format(lorem.split('\n')[4]))
print()
print('CACHE:')
print('{!r}'.format(linecache.getline(filename, 5)))

cleanup(filename)

返回的各行包括末尾的一个换行符。

1.3 处理空行

返回值总是在行末尾包含一个换行符,所以如果文本行为空,则返回值就是一个换行符。

# Blank lines include the newline
print('BLANK : {!r}'.format(linecache.getline(filename, 8)))

cleanup(filename)

输入文件的第8行不包含任何文本。

1.4 错误处理

如果所请求的行号超出了文件中合法行号的范围,则getline()会返回一个空串。

# The cache always returns a string, and uses
# an empty string to indicate a line which does
# not exist.
not_there = linecache.getline(filename, 500)
print('NOT THERE: {!r} includes {} characters'.format(
    not_there, len(not_there)))

输入文件只有15行,所以请求第500行就类似于试图越过文件末尾继续读文件。

读取一个不存在的文件时,也采用同样的方式处理。 

# Errors are even hidden if linecache cannot find the file
no_such_file = linecache.getline(
    'this_file_does_not_exist.txt', 1,
)
print('NO FILE: {!r}'.format(no_such_file))

调用者试图读取数据时,这个模块不会产生异常。

1.5 读取Python源文件

由于生成traceback跟踪记录时linecache使用得非常频繁,其关键特性之一是能够指定模块的基名在导入路径中查找Python源模块。

# Look for the linecache module, using
# the built in sys.path search.
module_line = linecache.getline('linecache.py', 3)
print('MODULE:')
print(repr(module_line))

# Look at the linecache module source directly.
file_src = linecache.__file__
if file_src.endswith('.pyc'):
    file_src = file_src[:-1]
print('\nFILE:')
with open(file_src, 'r') as f:
    file_line = f.readlines()[2]
print(repr(file_line))

如果linecache中的缓存填充代码在当前目录中无法找到指定名的文件,那么它会在sys.path中搜索指定名的模块。这个例子要查找linecache.py。由于当前目录中没有这个文件副本,所以会找到标准库中相应的文件。

posted @ 2020-03-15 10:46  SmallGrayCode  阅读(899)  评论(0编辑  收藏  举报