Почему linecache проверяет длину элементов кортежа в кеше? - PullRequest
0 голосов
/ 27 июня 2018

В https://github.com/python/cpython/blob/3.6/Lib/linecache.py есть 3 экземпляра этого

В getines

def getlines(filename, module_globals=None):
    if filename in cache:
        entry = cache[filename]
        if len(entry) != 1:
            return cache[filename][2]

В updatecache

def updatecache(filename, module_globals=None):
    if filename in cache:
        if len(cache[filename]) != 1:
            del cache[filename]

В lazycache

def lazycache(filename, module_globals):
    if filename in cache:
        if len(cache[filename]) == 1:
            return True
        else:
            return False

Я пишу свою собственную версию linecache, и чтобы написать тесты для нее, мне нужно понять сценарий, в котором кортеж может иметь длину 1

Был один сценарий, в котором выполнялась инструкция в getlines. Это было, когда файл был доступен в первый раз и сохранен в кеше, а затем удален, прежде чем получить к нему доступ во второй раз. Но я до сих пор не могу понять, почему это происходит в двух других функциях.

Было бы очень полезно, если бы кто-то мог помочь мне понять цель использования этой проверки длины.

1 Ответ

0 голосов
/ 27 июня 2018

Посмотрите на места, где код хранит значения в кеше. Он может хранить два различных типа значений в cache[filename]:

  • 4 кортежа размера, времени мода, списка строк и имени ( здесь и здесь ).
  • 1-кортеж функции, которая возвращает список строк по запросу ( здесь ).

1-кортеж используется для настройки отложенной загрузки модулей. Обычные файлы, чтобы их лениво загружать, вы просто open и read. Но источник модуля может быть доступен из загрузчика модуля (найден через систему импорта), но недоступен только при открытии и чтении файла, например, zipimport модулей. Так что lazycache должен спрятать метод загрузчика get_source, поэтому, если позже ему понадобятся строки, он может их получить.

И это означает, что всякий раз, когда использует эти значения кэша, он должен проверять, какого рода он хранится, и делать разные вещи. Если ему нужны строки сейчас, и у него есть ленивый 1-кортеж, он должен загрузить строки (через updatecache; если он проверяет на удаление кэша и находит ленивый кортеж, который никогда не оценивался, он сбрасывает его; и т.д.

Также обратите внимание, что в updatecache, если он загружает файл из ленивого 1-го кортежа, у него нет времени модификации, что означает, что в checkcache он не может проверить, устарел ли файл , Но это хорошо для источника модуля - даже если вы измените файл, старая версия все еще остается той, которая import ed и используется.


Если бы вы разрабатывали это с нуля, а не взламывали что-то, что было в stdlib с ранних 1.x темных веков, вы, вероятно, разработали бы это совсем по-другому. Например, вы можете использовать класс или два класса, реализующих один и тот же интерфейс.

Также обратите внимание, что огромный кусок кода в linecache предназначен для решения особых случаев, связанных с загрузкой исходного кода модуля, если вы не пытаетесь создать что-то, что отражается в коде Python (как это делает traceback ), вам не нужно ничего из. (И даже если вы делаете , вы, вероятно, захотите использовать модуль inspect вместо непосредственного общения с системой импорта.)

Таким образом, linecache может быть не лучшим примером кода, на котором будет основан ваш собственный строковый кеш.

...