|
Для Python-программистаСпециальный инструмент для отладки Анализ интерфейсов объектовВ Python утиная типизация поэтому лично мне иногда очень хочется посмотреть, какие методы поддерживаются разными объектами. Был написан такой скрипт: #!/usr/bin/python3
import sys
import os
import getopt
def ins_to_line(b, i, s):
return b[:s] + i + b[s+len(i):]
def desc(tts, filter_f, pr_desc):
f = {}
for tt in tts:
t = getattr(__builtins__, tt)
for n in dir(t):
if n in f:
f[n].append(tt)
else:
f[n] = [tt]
l = 0
for n, a in sorted(f.items(), key=lambda x: x[0]):
l = max(l, len(n))
s = l
ins = {}
for i in tts:
s += 2
ins[i] = s
s += len(i)
ss = '. ' * (int(s/2)+1)
b_line = ss[1:s+1], ss[0:s]
pp = 0
for n, a in sorted(f.items(), key=lambda x: x[0]):
if filter_f(len(a)):
pp = 1 - pp
if pr_desc:
print('=' * 59)
t = ins_to_line(b_line[pp], n, 0)
for i in a:
t = ins_to_line(t, i, ins[i])
print(t)
if pr_desc:
print('_ ' * 30)
print(getattr(getattr(__builtins__, a[0]), n).__doc__)
def usage():
print((
'Usage:\n'
' {0} -[hd1nN] type_name_1 type_name_2 ...\n'
'Options:\n'
' Filters:\n'
' -1 print methods that present only in one cless\n'
' -n methods presented in not all clases\n'
' -N methods presented in all classes\n'
' -A all methods (default)\n'
' Detallisations:\n'
' -d print x.__doc__\n'
' -h this message and exit\n'
'Example:\n'
' {0} -1 int bool'
).format(os.path.basename(sys.argv[0])))
def main():
optlist, args = getopt.getopt(sys.argv[1:], 'hd1nN')
args_l = len(args)
if args_l == 0:
usage()
return
number = lambda x: True # All
print_description = False
for k, v in optlist:
if k == '-1':
number = lambda x: x == 1
elif k == '-n':
number = lambda x: x < args_l
elif k == '-N':
number = lambda x: x == args_l
elif k == '-A':
pass
elif k == '-d':
print_description = True
elif k == '-h':
usage()
return
else:
raise Exception('How?!')
desc(args, number, print_description)
if __name__ == '__main__':
main()
Примеры использования: Вывести методы, которые присутствую только в одном из перечисленных классов: $ type_cmp -1 int str __abs__ . . . . . int . . __and__. . . . . .int. . . __bool__. . . . . int . . __ceil__ . . . . .int. . . __contains__. . . . . .str __divmod__ . . . .int. . . ... Вывести методы, которые присутствуют строго во всех из перечисленных классов: $ type_cmp -N int list dict __class__ . . . . int .list .dict __delattr__. . . .int. list. dict __doc__ . . . . . int .list .dict __eq__ . . . . . .int. list. dict __format__. . . . int .list .dict ... Вывести все методы с описаниями: $ type_cmp.py -d dict =========================================================== __class__ . . . . dict _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ type(object) -> the object's type type(name, bases, dict) -> a new type =========================================================== __contains__ . . .dict _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ D.__contains__(k) -> True if D has a key k, else False ... Специальный инструмент для отладкиМне приходится сталкиваться с большими массивами неподдерживаемого кода, в котором надо разбираться. В конце концов я написал такой модуль: import inspect
class magic_object:
def __init__(o, c, f, a, k):
o.h = c(*a, **k)
o.f = f
o.f("%s.__init__(*%s, **%s)" % (id(o.h), repr(a), repr(k)))
def __getattr__(o, name):
def d(*a, **k):
r = getattr(o.h, name)(*a, **k)
o.f("%s.%s(*%s, **%s) -> %s" % (id(o.h), name, repr(a), repr(k), repr(r)))
return r
return d
class magic_class:
def __init__(o, c, f):
o.c = c
o.f = f
def __call__(o, *a, **k):
return magic_object(o.c, o.f, a, k)
def magic_printing_func(x):
print "\033[44;34;1m*\033[0m %s" % x
def make_magic(the_class, printing_func=None):
if printing_func is None:
printing_func = magic_printing_func
# globals()[the_class.__name__] = magic_class(the_class, printing_func)
inspect.currentframe().f_back.f_globals[the_class.__name__] = magic_class(
the_class, printing_func
)
Пользоваться очень просто. Делаете из этого модуль, подключаете его и вызываете для любого класса магию. После этого всё, что происходит с объектами этого класса будет протоколироваться. class T:
def a(o):
pass
# запускаем магию
make_magic(T) # <--- вот оно
# дальше весь код оставляем без изменений, магия работает
t = T()
t.a()
Вы можете связаться со мной по e-mail a.michurin@gmail.com.
|