Рубрики
Без рубрики

linecache – эффективное чтение текстовых файлов

Автор оригинала: Doug Hellmann.

Цель:

Получение строк текста из файлов или импортированного Python модули, содержащие кеш результатов, чтобы сделать чтение многих строки из того же файла более эффективны.

Модуль linecache используется в других частях стандартной библиотеки Python при работе с исходными файлами Python. Реализация кеша хранит в памяти содержимое файлов, разбитое на отдельные строки. API возвращает запрошенную строку (строки) путем индексации в list и экономит время на многократное чтение файла и синтаксический анализ строк, чтобы найти нужную. Это особенно полезно при поиске нескольких строк в одном файле, например, при создании трассировки для отчета об ошибке.

Данные испытаний

Этот текст, созданный генератором Lorem Ipsum, используется как входной образец.

linecache_data.py

import os
import tempfile

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)

Чтение определенных строк

Номера строк файлов, считываемых модулем linecache , начинаются с 1, но обычно списки начинают индексировать массив с 0.

linecache_getline.py

import linecache
from linecache_data import *

filename  make_tempfile()

# 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)

Каждая возвращенная строка включает завершающий символ новой строки.

$ python3 linecache_getline.py

SOURCE:
'fermentum id, nonummy a, nonummy sit amet, ligula. Curabitur'

CACHE:
'fermentum id, nonummy a, nonummy sit amet, ligula. Curabitur\n'

Обработка пустых строк

Возвращаемое значение всегда включает новую строку в конце строки, поэтому, если строка пуста, возвращаемое значение – это просто новая строка.

linecache_empty_line.py

import linecache
from linecache_data import *

filename  make_tempfile()

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

cleanup(filename)

В восьмой строке входного файла нет текста.

$ python3 linecache_empty_line.py

BLANK : '\n'

Обработка ошибок

Если запрошенный номер строки выпадает из диапазона допустимых строк в файле, getline () возвращает пустую строку.

linecache_out_of_range.py

import linecache
from linecache_data import *

filename  make_tempfile()

# 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)))

cleanup(filename)

Во входном файле всего 15 строк, поэтому запрос строки 500 похож на попытку чтения после конца файла.

$ python3 linecache_out_of_range.py

NOT THERE: '' includes 0 characters

Таким же образом выполняется чтение из несуществующего файла.

linecache_missing_file.py

import linecache

# 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))

Модуль никогда не вызывает исключения, когда вызывающий абонент пытается прочитать данные.

$ python3 linecache_missing_file.py

NO FILE: ''

Чтение исходных файлов Python

Поскольку linecache очень интенсивно используется при создании трассировок, одной из его ключевых функций является возможность найти исходные модули Python в пути импорта, указав базовое имя модуля.

linecache_path_search.py

import linecache
import os

# 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 . Поскольку в текущем каталоге нет копии, вместо него будет найден файл из стандартной библиотеки.

$ python3 linecache_path_search.py

MODULE:
'This is intended to read lines from modules imported -- hence
if a filename\n'

FILE:
'This is intended to read lines from modules imported -- hence
if a filename\n'

Смотрите также