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.
Заключение
С помощью возможностей интроспекции удается рассмотреть фазы работы транслятора Python: лексический анализ, синтаксический разбор и генерации кода для интерпретатора, саму работу интерпретатора можно видеть при помощи отладчика.
Вместе с тем, в этой лекции было дано представление об использовании профайлера для исследования того, на что больше всего тратится процессорное время в программе, а также затронуты некоторые аспекты оптимизации Python–программ и варианты оптимизации кода на Python по скорости.
Наконец, интроспекция позволяет исследовать не только строение программы, но и объектов, с которыми работает эта программа. Были рассмотрены возможности Python по получению информации об объектах — этом основном строительном материале, из которого складываются данные любой Python–программы.