Шрифт:
.…
Интересны некоторые функции, которые предоставляют информацию об исходном коде объектов:
Листинг
>>> 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