Язык программирования Python.
Модуль inspect.
Основное назначение модуля inspect — давать приложению информацию о модулях, классах, функциях, трассировочных объектах, фреймах исполнения и кодовых объектах. Именно модуль inspect позволяет заглянуть «на кухню» интерпретатора Python.
Модуль имеет функции для проверки принадлежности объектов различным типам, с которыми он работает:
| Функция | Проверяемый тип |
|---|---|
| inspect.isbuiltin | Встроенная функция |
| inspect.isclass | Класс |
| inspect.iscode | Код |
| inspect.isdatadescriptor | Описатель данных |
| inspect.isframe | Фрейм |
| inspect.isfunction | Функция |
| inspect.ismethod | Метод |
| inspect.ismethoddescriptor | Описатель метода |
| inspect.ismodule | Модуль |
| inspect.isroutine | Функция или метод |
| inspect.istraceback | Трассировочный объект |
Пример:
>>> import inspect.
>>> inspect.isbuiltin(len).
True.
>>> inspect.isroutine(lambda x: x+1).
True.
>>> inspect.ismethod(''.split).
False.
>>> inspect.isroutine(''.split).
True.
>>> inspect.isbuiltin(''.split).
True.
Объект типа модуль появляется в Python–программе благодаря операции импорта. Для получения информации о модуле имеются некоторые функции, а объект–модуль обладает определенными атрибутами, как продемонстрировано ниже:
>>> import inspect.
>>> inspect.ismodule(inspect).
True.
>>> inspect.getmoduleinfo('/usr/local/lib/python2.3/inspect.pyc').
('inspect', '.pyc', 'rb', 2).
>>> inspect.getmodulename('/usr/local/lib/python2.3/inspect.pyc').
'inspect'.
>>> inspect.__name__
'inspect'.
>>> inspect.__dict__
...
>>> inspect.__doc__
...Get useful information from live Python objects.\n\nThis module encapsulates.
....
Интересны некоторые функции, которые предоставляют информацию об исходном коде объектов:
>>> import inspect.
>>> inspect.getsourcefile(inspect) # имя файла исходного кода.
'/usr/local/lib/python2.3/inspect.py'.
>>> inspect.getabsfile(inspect) # абсолютный путь к файлу.
'/usr/local/lib/python2.3/inspect.py'.
>>> print inspect.getfile(inspect) # файл кода модуля.
/usr/local/lib/python2.3/inspect.pyc.
>>> print inspect.getsource(inspect) # исходный текст модуля (в виде строки).
# -*- coding: iso–8859–1 -*- ""...Get useful information from live Python objects.
...
>>> import smtplib.
>>> # Комментарий непосредственно перед определением объекта:
>>> inspect.getcomments(smtplib.SMTPException).
'# Exception classes used by this module.\n'.
>>> # Теперь берем строку документирования:
>>> inspect.getdoc(smtplib.SMTPException).
'Base class for all exceptions raised by this module.'.
С помощью модуля inspect можно узнать состав аргументов некоторой функции с помощью функции inspect.getargspec():
>>> import inspect.
>>> def f(x, y=1, z=2):
... return x + y + z.
...
>>> def g(x, *v, **z):
... return x.
...
>>> print inspect.getargspec(f).
(['x', 'y', 'z'], None, None, (1, 2)).
>>> print inspect.getargspec(g).
(['x'], 'v', 'z', None).
Возвращаемый кортеж содержит список аргументов (кроме специальных), затем следуют имена аргументов для списка позиционных аргументов ( *) и списка именованных аргументов ( **), после чего — список значений по умолчанию для последних позиционных аргументов. Первый аргумент–список может содержать вложенные списки, отражая структуру аргументов:
>>> def f((x1,y1), (x2,y2)):
... return 1.
...
>>> print inspect.getargspec(f).
([['x1', 'y1'], ['x2', 'y2']], None, None, None).
Классы (как вы помните) — тоже объекты, и о них можно кое–что узнать:
>>> import smtplib.
>>> s = smtplib.SMTP.
>>> s.__module__ # модуль, в котором был определен объект.
'smtplib'.
>>> inspect.getmodule(s) # можно догадаться о происхождении объекта.
<module 'smtplib' from '/usr/local/lib/python2.3/smtplib.pyc'>
Для визуализации дерева классов может быть полезна функция inspect.getclasstree(). Она возвращает иерархически выстроенный в соответствии с наследованием список вложенных списков классов, указанных в списке–параметре. В следующем примере на основе списка всех встроенных классов–исключений создается дерево их зависимостей по наследованию:
Import inspect, exceptions.
Def formattree(tree, level=0):
"""Вывод дерева наследований.
tree — дерево, подготовленное с помощью inspect.getclasstree(),
которое представлено списком вложенных списков и кортежей.
В кортеже entry первый элемент — класс, а второй — кортеж с его.
базовыми классами. Иначе entry — вложенный список.
level — уровень отступов.
""".
for entry in tree:
if type(entry) is type(()):
c, bases = entry.
print level * " ", c.__name__, \
"(" + ", ".join([b.__name__ for b in bases]) + ")".
elif type(entry) is type([]):
formattree(entry, level+1).
V = exceptions.__dict__.values().
Exc_list = [e for e in v.
If inspect.isclass(e) and issubclass(e, Exception)].
Formattree(inspect.getclasstree(exc_list)).
С помощью функции inspect.currentframe() можно получить текущий фрейм исполнения. Атрибуты фрейма исполнения дают информацию о блоке кода, исполняющегося в точке вызова метода. При вызове функции (и в некоторых других ситуациях) на стек кладется соответствующий этому фрейму блок кода. При возврате из функции текущим становится фрейм, хранившийся в стеке. Фрейм содержит контекст выполнения кода: пространства имен и некоторые другие данные. Получить эти данные можно через атрибуты фреймового объекта:
Import inspect.
Def f():
fr = inspect.currentframe().
for a in dir(fr):
if a[:2] != "__":
print a, ":", str(getattr(fr, a))[:70].
F().
В результате получается.
F_back : <frame object at 0x812383c>
F_builtins : {'help': Type help() for interactive help, or help(object) for help ab.
F_code : <code object f at 0x401d83a0, file "<stdin>", line 11>
F_exc_traceback : None.
F_exc_type : None.
F_exc_value : None.
F_globals : {'f': <function f at 0x401e0454>, '__builtins__': <module '__builtin__
F_lasti : 68.
F_lineno : 16.
F_locals : {'a': 'f_locals', 'fr': <frame object at 0x813c34c>}.
F_restricted : 0.
F_trace : None.
Здесь f_back — предыдущий фрейм исполнения (вызвавший данный фрейм), f_builtins — пространство встроенных имен, как его видно из данного фрейма, f_globals — пространство глобальных имен, f_locals — пространство локальных имен, f_code — кодовый объект (в данном случае — байт-код функции f()), f_lasti — индекс последней выполнявшейся инструкции байт-кода, f_trace — функция трассировки для данного фрейма (или None), f_lineno — текущая строка исходного кода, f_restricted — признак выполнения в ограничительном режиме.
Получить информацию о стеке интерпретатора можно с помощью функции inspect.stack(). Она возвращает список кортежей, в которых есть следующие элементы:
(фрейм–объект, имя_файла, строка_в_файле, имя_функции,
Список_строк_исходного_кода, номер_строки_в_коде).
Трассировочные объекты также играют важную роль в интроспективных возможностях языка Python: с их помощью можно отследить место возбуждения исключения и обработать его требуемым образом. Для работы с трассировками предусмотрен даже специальный модуль — traceback.
Трассировочный объект представляет содержимое стека исполнения от места возбуждения исключения до места его обработки. В обработчике исключений связанный с исключением трассировочный объект доступен посредством функции sys.exc_info() (это третий элемент возвращаемого данной функцией кортежа).
Трассировочный объект имеет следующие атрибуты:
• tb_frame Фрейм исполнения текущего уровня.
• tb_lineno и tb_lasti Номер строки и инструкции, где было возбуждено исключение.
• tb_next Следующий уровень стека (другой трассировочный объект).
Одно из наиболее частых применений модуля traceback — «мягкая» обработка исключений с выводом отладочной информации в удобном виде (в лог, на стандартный вывод ошибок и т.п.):
#!/usr/bin/python.
Def dbg_except():
"""Функция для отладки операторов try–except""".
import traceback, sys, string.
print sys.exc_info().
print " ".join(traceback.format_exception(*sys.exc_info())).
Def bad_func2():
raise StandardError.
Def bad_func():
bad_func2().
Try:
bad_func().
Except:
dbg_except().
В результате получается примерно следующее:
(<class exceptions.StandardError at 0x4019729c>,
<exceptions.StandardError instance at 0x401df2cc>,
<traceback object at 0x401dcb1c>).
Traceback (most recent call last):
File "pr143.py", line 17, in ?
bad_func().
File "pr143.py", line 14, in bad_func.
bad_func2().
File "pr143.py", line 11, in bad_func2.
raise StandardError.
StandardError.
Функция sys.exc_info() дает кортеж с информацией о возбужденном исключении (класс исключения, объект исключения и трассировочный объект). Элементы этого кортежа передаются как параметры функции traceback.format_exception(), которая и печатает информацию об исключении в уже знакомой форме. Модуль traceback содержит и другие функции (о них можно узнать из документации), которые помогают форматировать те или иные части информации об исключении.
Разумеется, это еще не все возможности модуля inspect и свойств интроспекции в Python, а лишь наиболее интересные функции и атрибуты. Подробнее можно прочитать в документации или даже в исходном коде модулей стандартной библиотеки Python.
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.