Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Cимпатичний зневаджувальний друк

with one comment

Альтернативна назва статті: “Няшний дебажний print”. Але то звісно суржик, а ми – люди грамотні. 🙂 Ну, чи принаймі іноді знаємо коли неграмотні.

Відколи я покинув програмування в Visual Studio, і середовищах Borland, нормального дебагера я не бачив 😦 .

Тому доводиться руками часто роздруковувати поточний стан програми між виконанням інструкцій. Біда тільки що роздруковувати деколи доводиться купу даних, у складній структурі. І іноді важко знайти потрібні серед купи інших непотрібних логів в терміналі.

Проблема пошуку наших даних серед іншого тексту в терміналі вирішується просто – друкуємо в яскравих тонах.

Проблема виводу складних структур даних трохи складніша, бо:

>>> print [u'Тарас', u'Буник']
[u'\u0422\u0430\u0440\u0430\u0441', u'\u0411\u0443\u043d\u0438\u043a']

Ах, так, Python 3 лічить ввесь геморой з юнікодом, але ж на нього не перейшла ще жодна життєво важлива бібліотека (pylab, pygame, pylons). Тому ним займусь пізніше. Окрім того, якщо список буде мати вкладені підсписки, словники, і купу іншого – нам прийдеться туго.

>>> data = { 'name':u'Тарас', 'surname':u'Буник', 'bag':[u'Ключі', u'Гроші', u'Пропуск', u'Блокнот', u'Ручка', u'Туалетний папір', u'Телефон', '...' ]}
>>> data
{'bag': [u'\u041a\u043b\u044e\u0447\u0456', u'\u0413\u0440\u043e\u0448\u0456', u'\u041f\u0440\u043e\u043f\u0443\u0441\u043a', u'\u0411\u043b\u043e\u043a\u043d
\u043e\u0442', u'\u0420\u0443\u0447\u043a\u0430', u'\u0422\u0443\u0430\u043b\u0435\u0442\u043d\u0438\u0439 \u043f\u0430\u043f\u0456\u0440', u'\u0422\u0435\u04
3b\u0435\u0444\u043e\u043d', '...'], 'surname': u'\u0411\u0443\u043d\u0438\u043a', 'name': u'\u0422\u0430\u0440\u0430\u0441'}

Жах нах!

Може допомогти JSON:

>>> import json
>>> print json.dumps(data,indent=4,ensure_ascii = False)
{
    "bag": [
        "Ключі", 
        "Гроші", 
        "Пропуск", 
        "Блокнот", 
        "Ручка", 
        "Туалетний папір", 
        "Телефон", 
        "..."
    ], 
    "surname": "Буник", 
    "name": "Тарас"
}

Мрр, яка краса. Зверніть увагу на параметр ensure_ascii=False, без нього ви б знову побачили \u0411\u0443\u043d\u0438\u043a замість мого прізвища.

Правда і тут є проблеми:

>>> data['sqr'] = lambda x: x*x
>>> print json.dumps(data,indent=4,ensure_ascii = False)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
... блаблабла стек ...
  File "/usr/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <function <lambda> at 0x9e064fc> is not JSON serializable

JSON – це не Python, і навіть не JavaScript. Крапка.

Але на щастя, є модуль, над велосипедом якого я працював кілька годин. Ну, але краще пізно ніж ніколи:

>>> import pprint
>>> print pprint.pformat(data,4) # 4 - розмір відступу
{   'bag': [   u'\u041a\u043b\u044e\u0447\u0456',
               u'\u0413\u0440\u043e\u0448\u0456',
               u'\u041f\u0440\u043e\u043f\u0443\u0441\u043a',
               u'\u0411\u043b\u043e\u043a\u043d\u043e\u0442',
               u'\u0420\u0443\u0447\u043a\u0430',
               u'\u0422\u0443\u0430\u043b\u0435\u0442\u043d\u0438\u0439 \u043f\u0430\u043f\u0456\u0440',
               u'\u0422\u0435\u043b\u0435\u0444\u043e\u043d',
               '...'],
    'name': u'\u0422\u0430\u0440\u0430\u0441',
    'sqr': <function <lambda> at 0x9e064fc>,
    'surname': u'\u0411\u0443\u043d\u0438\u043a'}

На жаль, тут нема ключа ensure_ascii, але виявляється в рядків є чудовий метод decode(), і який знає хитре кодування 'unicode-escape'. В результаті:

>>> print pprint.pformat(data,4).decode('unicode-escape')
{   'bag': [   u'Ключі',
               u'Гроші',
               u'Пропуск',
               u'Блокнот',
               u'Ручка',
               u'Туалетний папір',
               u'Телефон',
               '...'],
    'name': u'Тарас',
    'sqr': <function <lambda> at 0x9e064fc>,
    'surname': u'Буник'}

І дебажив я код довго і щасливо. Не допомогло, тому хеппі енду не буде. Але це ще не кінець казки. Там ще гостросюжетний офігенно несподіваний поворот, який я ніяк не допишу, і який правда плазунів не стосується, тому не сильно не переживайте.

UPD: Diff

Можна також надрукувати різницю між двома об’єктами (зробити копію об’єкта, змінити оригінал, і дивитись що змінилось):

from difflib import ndiff

colors ={
    '-':91, # for diffs
    '+':92,
    '?':94,
}
def print_diff(a,b):
    a_lines = render_json(a).splitlines(1)
    b_lines = render_json(b).splitlines(1)
    diff = ndiff(a_lines,b_lines)

    for line in diff:
        print '\033[%sm%s\033[0m'% (colors.get(line[0],0), line[:-1])
Advertisements

Written by bunyk

Вересень 14, 2011 at 23:19

Оприлюднено в Кодерство

Tagged with

Одна відповідь

Subscribe to comments with RSS.

  1. […] з Інтроспектором та іншими утилітами для дебагу це вже тягне на якусь лібу. Напевне […]


Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: