Документация Python неофициальный перевод
Содержание страницы

27.12. inspect – Инспекция живых объектовinspect – Inspect live objects

Исходный код: Lib/inspect.py


Модуль inspect предоставляет несколько полезных функций для получения информации об активных объектах, таких как модули, классы, методы, функции, трассировки стека, объекты фреймов и объекты кода. Например, с его помощью можно просмотреть содержимое класса, получить исходный код метода, извлечь и отформатировать список аргументов функции или получить всю информацию, необходимую для отображения подробной трассировки стека.

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

27.12.1. Типы и членыTypes and members

Функция getmembers() извлекает члены объекта, такого как класс или модуль. Шестнадцать функций, имена которых начинаются с «is», в основном предоставляются как удобные варианты для второго аргумента getmembers(). Они также помогают определить, когда можно ожидать следующие специальные атрибуты:

Тип Атрибут Описание
модуль doc строка документации
  file filename (отсутствует для встроенных модулей)
класс doc строка документации
  module имя модуля, в котором был определён этот класс
метод doc строка документации
  name имя, под которым был определён этот метод
  func объект функции, содержащий реализацию метода
  self экземпляр, к которому привязан этот метод, или None
функция doc строка документации
  name имя, под которым была определена эта функция
  code объект кода, содержащий скомпилированную функцию байткод
  defaults кортеж значений по умолчанию для аргументов
  globals глобальное пространство имён, в котором была определена эта функция
трассировка tb_frame объект фрейма на этом уровне
  tb_lasti индекс последней предпринятой инструкции в байткоде
  tb_lineno текущий номер строки в исходном коде Python
  tb_next следующий внутренний объект traceback (вызванный на этом уровне)
фрейм f_back следующий внешний объект фрейма (вызывающий этот фрейм)
  f_builtins пространство имён builtins, видимое этим фреймом
  f_code объект кода, выполняющийся в этом фрейме
  f_globals глобальное пространство имён, видимое этим фреймом
  f_lasti индекс последней предпринятой инструкции в байткоде
  f_lineno текущий номер строки в исходном коде Python
  f_locals локальное пространство имён, видимое этим фреймом
  f_restricted 0 или 1, если фрейм находится в ограниченном режиме выполнения
  f_trace функция трассировки для этого фрейма, или None
код co_argcount количество аргументов (не включая * или ** args)
  co_code строка сырого скомпилированного байткода
  co_consts кортеж констант, используемых в байткоде
  co_filename имя файла, в котором был создан этот объект кода
  co_firstlineno номер первой строки в исходном коде Python
  co_flags битовая маска: 1=оптимизировано | 2=новые локальные | 4=*arg | 8=**arg
  co_lnotab кодированное отображение номеров строк на индексы байт-кода
  co_name имя, с которым был определён этот объект кода
  co_names кортеж имён локальных переменных
  co_nlocals количество локальных переменных
  co_stacksize требуемый размер стека виртуальной машины
  co_varnames кортеж имён аргументов и локальных переменных
встроенный doc строка документации
  name исходное имя этой функции или метода
  self экземпляр, к которому привязан метод, или None
inspect.getmembers(object[, predicate])

Возвращает все члены объекта в виде списка пар (имя, значение), отсортированных по имени. Если передан необязательный аргумент predicate, включаются только те члены, для которых предикат возвращает истинное значение.

Примечание

getmembers() не возвращает атрибуты метакласса, когда аргумент является классом (это поведение унаследовано от функции dir()).

inspect.getmoduleinfo(path)

Возвращает именованный кортеж ModuleInfo(name, suffix, mode, module_type) со значениями, описывающими, как Python будет интерпретировать файл по path, если это модуль, или None, если он не идентифицируется как модуль. В этом кортеже name – имя модуля без имени оборачивающего пакета, suffix – конечная часть имени файла (которая может быть не расширением, отделённым точкой), mode – режим open(), который будет использован ('r' или 'rb'), а module_type – целое число, представляющее тип модуля. module_type будет иметь значение, которое можно сравнить с константами, определёнными в модуле imp; подробнее о типах модулей см. документацию этого модуля.

inspect.getmodulename(path)

Возвращает имя модуля, задаваемое файлом path, без включения имён объемлющих пакетов. Используется тот же алгоритм, что и интерпретатор при поиске модулей. Если имя не удаётся сопоставить по правилам интерпретатора, возвращается None.

inspect.ismodule(object)

Возвращает True, если объект является модулем.

inspect.isclass(object)

Возвращает True, если объект является классом, встроенным или созданным в коде Python.

inspect.ismethod(object)

Возвращает True, если объект является связанным методом, написанным на Python.

inspect.isfunction(object)

Возвращает True, если объект является функцией Python, включая функции, созданные с помощью выражения lambda.

inspect.isgeneratorfunction(object)

Возвращает True, если объект является функцией-генератором Python.

inspect.isgenerator(object)

Возвращает True, если объект является генератором.

inspect.istraceback(object)

Возвращает True, если объект является трассировкой.

inspect.isframe(object)

Возвращает True, если объект является фреймом.

inspect.iscode(object)

Возвращает True, если объект является кодом.

inspect.isbuiltin(object)

Возвращает True, если объект является встроенной функцией или связанным встроенным методом.

inspect.isroutine(object)

Возвращает True, если объект является пользовательской или встроенной функцией или методом.

inspect.isabstract(object)

Возвращает True, если объект является абстрактным базовым классом.

inspect.ismethoddescriptor(object)

Возвращает true, если объект является дескриптором метода, но не если ismethod(), isclass(), isfunction() или isbuiltin() возвращают true.

Это, например, верно для int.__add__. Объект, проходящий эту проверку, имеет атрибут __get__, но не имеет атрибута __set__, а кроме того, набор атрибутов различается. __name__ обычно осмысленно, и __doc__ часто тоже.

Методы, реализованные через дескрипторы и также проходящие один из других тестов, возвращают false для теста ismethoddescriptor() просто потому, что другие тесты обещают больше – например, можно рассчитывать на наличие атрибута __func__ (и т.д.), когда объект проходит ismethod().

inspect.isdatadescriptor(object)

Возвращает True, если объект является дескриптором данных.

Дескрипторы данных имеют как атрибут __get__, так и атрибут __set__. Примеры: свойства (определённые в Python), getsets и элементы. Последние два определены на C, и для этих типов существуют более специфичные проверки, которые работают во всех реализациях Python. Обычно дескрипторы данных также имеют атрибуты __name__ и __doc__ (свойства, getsets и элементы имеют оба этих атрибута), но это не гарантируется.

inspect.isgetsetdescriptor(object)

Возвращает True, если объект является дескриптором getset.

Особенности реализации CPython: getsets – это атрибуты, определённые в модулях расширения через структуры PyGetSetDef. Для реализаций Python без таких типов этот метод всегда возвращает False.

inspect.ismemberdescriptor(object)

Возвращает True, если объект является дескриптором члена.

Особенность реализации CPython: Дескрипторы членов – это атрибуты, определяемые в модулях расширения через структуры PyMemberDef. Для реализаций Python без таких типов этот метод всегда возвращает False.

27.12.2. Получение исходного кодаRetrieving source code

inspect.getdoc(object)

Возвращает строку документации объекта, очищенную с помощью cleandoc().

inspect.getcomments(object)

Возвращает единой строкой все строки комментариев, непосредственно предшествующие исходному коду объекта (для класса, функции или метода) или находящиеся в начале исходного файла Python (если объект – модуль).

inspect.getfile(object)

Возвращает имя (текстового или бинарного) файла, в котором определён объект. Это вызовет TypeError, если объект является встроенным модулем, классом или функцией.

inspect.getmodule(object)

Пытается определить модуль, в котором был определён объект.

inspect.getsourcefile(object)

Возвращает имя исходного файла Python, в котором определён объект. Это вызовет TypeError, если объект является встроенным модулем, классом или функцией.

inspect.getsourcelines(object)

Возвращает список строк исходного кода и номер начальной строки для объекта. Аргументом может быть модуль, класс, метод, функция, трассировка, фрейм или объект кода. Исходный код возвращается в виде списка строк, соответствующих объекту, а номер строки указывает, где в исходном файле была найдена первая строка кода. Возбуждается исключение IOError, если исходный код не удается получить.

inspect.getsource(object)

Возвращает текст исходного кода для объекта. Аргументом может быть модуль, класс, метод, функция, трассировка, фрейм или объект кода. Исходный код возвращается в виде одной строки. Возбуждается исключение IOError, если исходный код не удается получить.

inspect.cleandoc(doc)

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

27.12.3. Классы и функцииClasses and functions

inspect.getclasstree(classes, unique=False)

Упорядочивает заданный список классов в иерархию вложенных списков. Если встречается вложенный список, он содержит классы, унаследованные от класса, запись которого непосредственно предшествует этому списку. Каждая запись представляет собой кортеж из двух элементов, содержащий класс и кортеж его базовых классов. Если аргумент unique равен true, в возвращаемой структуре появляется ровно одна запись для каждого класса из заданного списка. В противном случае классы, использующие множественное наследование, и их потомки будут появляться несколько раз.

inspect.getargspec(func)

Получает имена и значения по умолчанию аргументов функции Python. Возвращается именованный кортеж ArgSpec(args, varargs, keywords, defaults). args – это список имен аргументов. varargs и keywords – имена аргументов * и ** или None. defaults – это кортеж значений аргументов по умолчанию или None, если аргументов по умолчанию нет; если этот кортеж содержит n элементов, они соответствуют последним n элементам, перечисленным в args.

Устарело с версии 3.0: Используйте getfullargspec() вместо неё, которая предоставляет информацию об аргументах, передаваемых только по ключевому слову, и аннотациях.

inspect.getfullargspec(func)

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

FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)

args – список имён аргументов. varargs и varkw – имена аргументов * и ** или None. defaults – n-кортеж значений по умолчанию для последних n аргументов. kwonlyargs – список имён только ключевых аргументов. kwonlydefaults – словарь, сопоставляющий имена из kwonlyargs значениям по умолчанию. annotations – словарь, сопоставляющий имена аргументов аннотациям.

Первые четыре элемента в кортеже соответствуют getargspec().

inspect.getargvalues(frame)

Получает информацию об аргументах, переданных в конкретный фрейм. Возвращается именованный кортеж ArgInfo(args, varargs, keywords, locals). args – список имён аргументов. varargs и keywords – имена аргументов * и ** или None. locals – словарь локальных переменных данного фрейма.

inspect.formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue])

Форматирует читаемое описание аргументов из четырёх значений, возвращаемых getargspec(). Аргументы format* – это соответствующие необязательные функции форматирования, которые вызываются для преобразования имён и значений в строки.

inspect.formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue])

Форматирует красивое описание аргументов из четырёх значений, возвращаемых getargvalues(). Аргументы format* – это соответствующие необязательные функции форматирования, которые вызываются для преобразования имён и значений в строки.

inspect.getmro(cls)

Возвращает кортеж базовых классов класса cls, включая cls, в порядке разрешения методов (MRO). Ни один класс не встречается в этом кортеже более одного раза. Обратите внимание, что порядок разрешения методов зависит от типа cls. Если не используется особенная пользовательская метатипизация, cls будет первым элементом кортежа.

inspect.getcallargs(func[, *args][, **kwds])

Привязывает args и kwds к именам аргументов функции или метода Python func, как если бы она была вызвана с ними. Для привязанных методов также привязывает первый аргумент (обычно с именем self) к соответствующему экземпляру. Возвращается словарь, отображающий имена аргументов (включая имена аргументов * и **, если они есть) в их значения из args и kwds. В случае некорректного вызова func, т.е. когда func(*args, **kwds) вызвало бы исключение из-за несовместимой сигнатуры, возникает исключение того же типа и с тем же или похожим сообщением. Например:

>>> from inspect import getcallargs
>>> def f(a, b=1, *pos, **named):
...     pass
>>> getcallargs(f, 1, 2, 3)
{'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}
>>> getcallargs(f, a=2, x=4)
{'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}
>>> getcallargs(f)
Traceback (most recent call last):
...
TypeError: f() takes at least 1 argument (0 given)

Новое в версии 3.2.

27.12.4. Стек интерпретатораThe interpreter stack

Когда следующие функции возвращают «записи фреймов» (frame records), каждая запись представляет собой кортеж из шести элементов: объект фрейма, имя файла, номер текущей строки, имя функции, список строк контекста из исходного кода и индекс текущей строки в этом списке.

Примечание

Хранение ссылок на объекты фреймов (как в первом элементе записей фреймов, возвращаемых этими функциями) может привести к созданию циклических ссылок в программе. После создания циклической ссылки время жизни всех объектов, доступных из объектов, образующих цикл, может значительно увеличиться, даже если включён дополнительный детектор циклов Python. Если такие циклы необходимо создать, важно убедиться, что они явно разрываются, чтобы избежать задержки уничтожения объектов и увеличения потребления памяти.

Хотя детектор циклов перехватит их, уничтожение фреймов (и локальных переменных) можно сделать детерминированным, удалив цикл в блоке finally. Это также важно, если детектор циклов был отключён при компиляции Python или с помощью gc.disable(). Например:

def handle_stackframe_without_leak():
    frame = inspect.currentframe()
    try:
        # Выполнить действие с фреймом
    finally:
        del frame

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

inspect.getframeinfo(frame, context=1)

Возвращает информацию об объекте фрейма или traceback. Возвращается именованный кортеж Traceback(filename, lineno, function, code_context, index).

inspect.getouterframes(frame, context=1)

Возвращает список записей фреймов для фрейма и всех внешних фреймов. Эти фреймы представляют вызовы, которые привели к созданию frame. Первая запись в возвращаемом списке представляет frame; последняя запись представляет самый внешний вызов в стеке frame.

inspect.getinnerframes(traceback, context=1)

Возвращает список записей о фреймах для фрейма traceback и всех внутренних фреймов. Эти фреймы представляют вызовы, являющиеся следствием frame. Первый элемент списка представляет traceback; последний элемент представляет место, где было возбуждено исключение.

inspect.currentframe()

Возвращает объект фрейма для фрейма стека вызывающего.

Особенность реализации CPython: Эта функция полагается на поддержку стековых фреймов Python в интерпретаторе, которая не гарантируется во всех реализациях Python. Если запуск происходит в реализации без поддержки стековых фреймов Python, эта функция возвращает None.

inspect.stack(context=1)

Возвращает список записей о фреймах для стека вызывающего кода. Первый элемент возвращаемого списка представляет вызывающий код; последний элемент представляет самый внешний вызов в стеке.

inspect.trace(context=1)

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

27.12.5. Статическое получение атрибутовFetching attributes statically

Как getattr(), так и hasattr() могут запускать выполнение кода при получении или проверке существования атрибутов. Дескрипторы, такие как свойства, будут вызваны, и __getattr__() и __getattribute__() также могут быть вызваны.

Для случаев, когда требуется пассивная интроспекция, например, в инструментах документации, это может быть неудобно. getattr_static() имеет ту же сигнатуру, что и getattr(), но не выполняет код при получении атрибутов.

inspect.getattr_static(obj, attr, default=None)

Извлекает атрибуты без запуска динамического поиска через протокол дескрипторов, __getattr__() или __getattribute__().

Примечание: эта функция может быть не в состоянии получить все атрибуты, которые может получить getattr (например, динамически созданные атрибуты), и может найти атрибуты, которые getattr не может (например, дескрипторы, вызывающие AttributeError). Она также может возвращать объекты дескрипторов вместо членов экземпляра.

Если __dict__ экземпляра скрыт другим членом (например, свойством), то эта функция не сможет найти члены экземпляра.

Новое в версии 3.2.

getattr_static() не разрешает дескрипторы, например, дескрипторы слотов или getset-дескрипторы для объектов, реализованных на C. Возвращается объект дескриптора вместо базового атрибута.

С ними можно работать с помощью кода вроде следующего. Обратите внимание, что для произвольных getset-дескрипторов их вызов может запустить выполнение кода:

# Пример кода для разрешения встроенных типов дескрипторов
class _foo:
    __slots__ = ['foo']

slot_descriptor = type(_foo.foo)
getset_descriptor = type(type(open(__file__)).name)
wrapper_descriptor = type(str.__dict__['__add__'])
descriptor_types = (slot_descriptor, getset_descriptor, wrapper_descriptor)

result = getattr_static(some_object, 'foo')
if type(result) in descriptor_types:
    try:
        result = result.__get__()
    except AttributeError:
        # Дескрипторы могут вызывать AttributeError, чтобы
        # указать, что нет нижележащего значения
        # в этом случае сам дескриптор будет
        # придется сделать
        pass

27.12.6. Текущее состояние генератораCurrent State of a Generator

При реализации планировщиков корутин и в других продвинутых применениях генераторов полезно определять, выполняется ли генератор в данный момент, ожидает ли он запуска или возобновления, или уже завершился. getgeneratorstate() позволяет легко определить текущее состояние генератора.

inspect.getgeneratorstate(generator)

Возвращает текущее состояние генератора-итератора.

Возможные состояния:
  • GEN_CREATED: Ожидание начала выполнения.
  • GEN_RUNNING: В настоящее время выполняется интерпретатором.
  • GEN_SUSPENDED: в данный момент приостановлена на выражении yield.
  • GEN_CLOSED: выполнение завершено.

Новое в версии 3.2.