в чем смысл филкинга в контексте модуля логирования - PullRequest
0 голосов
/ 23 декабря 2018

Проходя через logging модуль и увидел это:

# next bit filched from 1.5.2's inspect.py
def currentframe():
    """Return the frame object for the caller's stack frame."""
    try:
        raise Exception
    except:
        return sys.exc_info()[2].tb_frame.f_back

if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
# done filching

Что означает фраза "филкинг" в этом контексте?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Как заметил Барни , комментарий , который гласит:

# next bit filched from 1.5.2's inspect.py

, использует слово для обозначения «скопировано из».То есть эта конкретная кодовая последовательность существует уже очень давно, начиная с версии Python 1.5.2.

Что здесь происходит (правка: эта часть вопроса была отредактирована!) просто но тонко.Любое исключение заставляет систему Python находить самый внутренний, в настоящее время активный обработчик except.В данном случае это самая следующая строка - так:

try:
    raise Exception
except:
    ...

переходит непосредственно к строке ....Тем не менее, у raise есть побочный эффект , который является ключом ко всему.Побочным эффектом является то, что raise заставляет стек трассировки содержать в качестве самой последней записи 1 состояние выполнения, указывающее на саму строку raise.

Функция sys.exc_info() возвращает кортеж с тремя элементами: тип исключения, значение исключения - здесь не было передано никакого значения, потому что обработчик не нуждается в нем, - и (весь) стек трассировки.[2] извлекает этот стек трассировки из кортежа, отбрасывая тип и значение исключения.

Структура стека трассировки несколько сложна, но в каждом экземпляре стека трассировки есть атрибут .tb_frame.Он содержит информацию о кадре стека, который был активен при возникновении исключения.Поскольку это стек активаций функций, его предшественником является состояние, которое было активным при вызове currentframe, поэтому это кадр вызывающего абонента.

Этот метод определения местоположения кадра вызывающего абонента не очень эффективен (и, как holdenweb указывает , специфично для интерпретатора CPython), поэтому, если sys имеет функцию _getframe, файл повторно связывается currentframe, чтобы вызвать sys._getframe(3).(Я не уверен, что здесь делает константа 3, поскольку другая версия эффективно возвращает то, что вернуло бы sys._getframe(0). Правка 2: при дальнейшей проверке магическая константа 3 заботится о том, чтобы обработчик журнала вызывал _log, который вызывает findCaller, который вызывает currentframe. Это еще один хак эффективности, так как findCaller поднимается по каждому фрейму стека в поисках того, что встречается в каком-то файле , отличном от , самого кода модуля протоколирования.Лучшее замечание.)


1 Помните, что стек - это любая структура данных, которая ведет себя по принципу «последний пришел - первым вышел» (LIFO).Интерпретатор Python управляет множеством различных, но более или менее одновременных стеков, включая обработчики исключений и обычный механизм вызова функций.

0 голосов
/ 23 декабря 2018

Это код, который вы не хотите брать в качестве хорошего примера!Прежде всего, это специфично для реализации CPython и поэтому не будет работать в PyPy, Jython, Iron Python и т. Д.

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

«Фильтрация» происходит без разрешения, так что это всего лишь опрометчивый способ сказать «Я скопировал и вставил из библиотеки с открытым исходным кодом».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...