Тут недавно
меня попросили выдать информацию о
происходящем в runtime в Naudoc/Zope. Конкретнее,
что там есть такого в обрабатываемом
документе, в процессе воркфлоу.
Один из простых
способов получить такую информацию
заключается в применении интроспекции.
Недолгое гугление не принесло
исчерпывающего готового рецепта, только
составные части в стиле do it yourself.
Например. Часть
первая
Guide to Python
introspection
How to spy on your
Python objects
Отсюда я взял
первую часть рецепта, добавив в него
чуть-чуть отсебятины, в частности обертку
для перенаправления stdout в список строк
(из
class ListStream:
def __init__(self):
self.data = []
def write(self, s):
self.data.append(s)
def interrogate(item):
"""Print useful information about item.
Returns list of strings.
"""
sys.stdout = x = ListStream()
if hasattr(item, '__name__'):
print "NAME: ", item.__name__
if hasattr(item, '__class__'):
print "CLASS: ", item.__class__.__name__
print "ID: ", id(item)
print "TYPE: ", type(item)
print "VALUE: ", repr(item)
print "CALLABLE:",
if callable(item):
print "Yes"
else:
print "No"
if hasattr(item, '__doc__'):
doc = getattr(item, '__doc__')
doc = doc.strip() # Remove leading/trailing whitespace.
firstline = doc.split('\n')[0]
print "DOC: ", firstline
print "ATTRIBUTES:", vars(item)
print "NAMES: ", dir(item)
sys.stdout = sys.__stdout__
return x.data
|
В вывод попало
нечто вроде
NAME:
ttt
CLASS:
HTMLDocument
ID:
77748944
TYPE:
<type 'ImplicitAcquirerWrapper'>
VALUE:
<HTMLDocument at /docs/storage/members/valik/test/ttt>
CALLABLE:
Yes
DOC:
Subclassed Document type
ATTRIBUTES:
{'contributors': (), 'nd_uid': '143058357876X4990437627', 'distribution_log': [], '_safety_belt': 'None',
'id': 'ttt', 'subject': (), 'category': 'BGClientCard', '_last_safety_belt': '', 'skip_catalogize': [],
'subscribed_users': {}, '_last_safety_belt_editor': 'zope', '_Delete_objects_Permission': ('Director', 'Manager'),
'text_format': 'html', 'version': <Products.CMFNauTools.ContentVersions.VersionsContainer object at 0x4bf86e0>,
'_objects': ({'meta_type': 'Object Manager', 'id': 'version'},),
'followup': <Products.CMFNauTools.TaskItemContainer.TaskItemContainer object at 0x4bc9230>,
'_version_tag': -8584773770338532410, 'portal_type': 'HTMLDocument', 'registry_data': {},
'language': 'ru', 'rights': '', 'expiration_date': None, '_Manage_properties_Permission': ('Author', 'Owner', 'Writer'),
'_owner': (['acl_users'], 'zope'), 'changes_log': [], '__ac_local_roles__': {'zope': ['Owner']}}
NAMES:
['COPY', 'COPY__roles__', 'Category', 'CategoryAttributes', 'Contributors', 'Contributors__roles__',
'CookedBody', 'CookedBody__roles__', 'CreationDate', 'CreationDate__roles__', 'Creator', 'Creator__roles__', ...
|
Заказчику
этого было мало, он захотел получить
сигнатуры методов, в смысле, имена
параметров. На это я ответил, что самый
простой способ получить эту информацию,
это grep по исходному коду.
Но можно иначе.
Например. Часть
вторая
inspect – Inspect
live objects
Purpose: The inspect
module provides functions for introspecting on live objects and their
source code.
If the .py file is
available for a module, the original source code for the class or
method can be retrieved using getsource() and
getsourcelines().
import inspect import example print inspect.getsource(example.A.get_name)
…
In addition to the documentation for a function
or method, it is possible to ask for a complete specification of the
arguments the callable takes, including default values. The
getargspec() function returns a tuple
containing the list of positional argument names, the name of any
variable positional arguments (e.g., *args),
the names of any variable named arguments (e.g., **kwds),
and default values for the arguments. If there are default values,
they match up with the end of the positional argument list.
import inspect import example arg_spec = inspect.getargspec(example.module_level_function) print 'NAMES :', arg_spec[0] print '* :', arg_spec[1] print '** :', arg_spec[2] print 'defaults:', arg_spec[3] args_with_defaults = arg_spec[0][-len(arg_spec[3]):] print 'args & defaults:', zip(args_with_defaults, arg_spec[3])
То есть, получив в первой части список
методов класса, можно скормить его
inspect-у и получить как исходный код, так
и спецификацию аргументов.
Но этого я
делать не стал, грепать попроще таки.
original post http://vasnake.blogspot.com/2015/05/python-introspection.html

Комментариев нет:
Отправить комментарий