Python 3.x: альтернативная реализация pprint

Стандартный модуль pprint удобен при работе со списками, словарями и т.д. Но иногда совершенно непригодно для использования с пользовательскими классами:

  • Единственный способ заставить его печатать пригодную для использования информацию об объекте некоторого класса — это переопределить __repr__, но что, если в моем классе уже есть хороший, eval()'способный __repr__, который не показывает информацию, которую я хочу видеть в выводе pprint?

  • Хорошо, я напишу ориентированный на печать __repr__, но в этом случае невозможно красиво напечатать что-то внутри моего класса:

.

class Data:
    def __init__(self):
        self.d = {...}

Я не могу красиво напечатать содержимое self.d, я могу вернуть только однострочное представление (по крайней мере, не играя с трассировкой стека и т. д.). - Переопределение PrettyPrinter не вариант, я не хочу делать это каждый раз, когда хочу красиво напечатать один и тот же класс.

Итак... Существуют ли какие-либо альтернативы pprint, которые позволяют сделать пользовательский класс красивым для печати?


person Equidamoid    schedule 19.05.2013    source источник
comment
Найдено pypi.python.org/pypi/pretty/0.1 , но, похоже, только py2.X   -  person Equidamoid    schedule 19.05.2013
comment
Я могу вернуть только однострочное представление — почему? Например, NumPy возвращает многострочные repr(), которые прекрасно работают. Вот пример в виде строки Python: "array([(0, 0, (0, 0, 0)), (0, 0, (0, 0, 0)), (0, 0, (0, 0, 0)),\n (0, 0, (0, 0, 0))], \n dtype=[('foo', 'u1'), ('bar', '<u2'), ('baz', [('fbb', 'u1'), ('oaa', 'u1'), ('orz', 'u1')])])" . Это нормально с eval(), с "массивом" в пространстве имен.   -  person kampu    schedule 19.05.2013
comment
@kampu Я имел в виду, что не могу вернуть многострочную строку, потому что это нарушит отступ pprint.   -  person Equidamoid    schedule 19.05.2013
comment
Да, я пытался отредактировать и указать, что я только что это понял, но 5-минутный период отсрочки редактирования истек. В любом случае, приятно знать, что мы на одной волне :)   -  person kampu    schedule 19.05.2013
comment
@Equidamoid, если вам нужно решение для Python 3, укажите это в своем вопросе и добавьте соответствующий тег.   -  person utapyngo    schedule 19.05.2013
comment
И почему создание подкласса PrettyPrinter не вариант?   -  person utapyngo    schedule 19.05.2013
comment
И почему невозможно красиво напечатать что-то внутри вашего класса в случае написания пользовательского __repr__? Строка, которую он возвращает, может содержать представление любого поля вашего объекта.   -  person utapyngo    schedule 19.05.2013
comment
@utapyngo сделано. Упс, фраза о подклассах немного неверна %) Я просто не хочу добавлять поддержку конкретного класса в PrettyPrinter (потому что кода, специфичного для класса, там не должно быть), и ищу универсальное решение, такое как один упомянутый в моем 1-м комментарии.   -  person Equidamoid    schedule 19.05.2013
comment
@utapyngo невозможно создать правильную многострочную строку в __repr__ из-за неизвестного текущего уровня отступа.   -  person Equidamoid    schedule 20.05.2013


Ответы (4)


Существует улучшенный и поддерживаемый порт Python 2.x/3.x "красивой" библиотеки в IPython: https://ipython.readthedocs.io/en/stable/api/generated/IPython.lib.pretty.html

person Mikhail Korobov    schedule 08.09.2013

Если красивый модуль удовлетворяет ваши потребности, вы можете заставить его работать с Python 3.

  1. Загрузите и распакуйте файл pretty.py.
  2. Запустите на нем 2to3:

    python -m lib2to3 -w pretty.py
    
  3. Закомментируйте следующие строки:

    569: types.DictProxyType:        _dict_pprinter_factory('<dictproxy {', '}>'),
    580: xrange:                     _repr_pprint,
    
  4. Поместите файл рядом с вашим скриптом.

  5. Импортируйте как обычно:

    import pretty
    
person utapyngo    schedule 19.05.2013
comment
@Equidamoid: у тебя получилось? - person utapyngo; 22.05.2013
comment
Однако pretty не нравится numpy.ndarray =( - person Equidamoid; 25.05.2013

для красивой печати вы можете искать __str__ вместо (или также) __repr__

e.g.

>>> import datetime
>>> now = datetime.datetime.now()
>>> print now
2013-05-19 13:00:34.085383
>>> print repr(now)
datetime.datetime(2013, 5, 19, 13, 0, 34, 85383)
person second    schedule 19.05.2013
comment
Теперь представьте, что вместо datetime у вас есть класс с несколькими dict, достаточно большими, чтобы они не помещались в одну строку терминала. И тогда у вас есть dict с несколькими такими объектами... Это мой случай. - person Equidamoid; 20.05.2013

Вы можете создать универсальное решение, которое печатает содержимое полей объекта, создав подкласс PrettyPrinter. obj.__dict__ даст вам словарь всех полей obj.

Или вы можете просто использовать obj.__class__.__name__ + pformat(obj.__dict__).

person utapyngo    schedule 19.05.2013