лучший способ реализовать пользовательские симпатичные принтеры - PullRequest
21 голосов
/ 15 июля 2010

Настройка pprint.PrettyPrinter

В документации для модуля pprint упоминается, что метод PrettyPrinter.format предназначен для обеспечения возможности настройки форматирования.

Я понимаю, что возможнопереопределите этот метод в подклассе, но это, кажется, не обеспечивает способа применения методов базового класса к переносу строк и отступам.

  • Я что-то здесь упускаю?
  • Есть ли лучший способ сделать это (например, другой модуль)?

Альтернативы?

Я проверил модуль pretty, который выглядит интересным, но, похоже, не дает возможности настроить форматирование классов из других модулей без изменения этих модулей.

* 1022Я думаю, что я ищу то, что позволило бы мне обеспечить отображение типов (или, возможно, функций), которые идентифицируют типы для подпрограмм, которые обрабатывают узел.Подпрограммы, которые обрабатывают узел, берут узел и возвращают его строковое представление вместе со списком дочерних узлов.И так далее.

Почему я смотрю на симпатичную печать

Моя конечная цель - компактная печать пользовательских форматированных разделов в формате DocBook xml.etree.ElementTree.

(Я был удивлен, что не нашел больше поддержки Python для DocBook. Может быть, я что-то там упустил.)

Я встроил некоторые базовые функции в клиент под названием xmlearn , который использует LXML .Например, чтобы выгрузить файл Docbook, вы могли бы:

xmlearn -i docbook_file.xml dump -f docbook -r book

Это довольно глупо, но оно дало мне информацию, которую я искал.

xmlearn имеет и другие функции, такие как возможность создания графического изображения и создания дампов, показывающих взаимосвязи между тегами в XML-документе.Они в значительной степени не связаны с этим вопросом.

Вы также можете выполнить дамп на произвольную глубину или указать XPath в качестве набора начальных точек.Материал XPath устарел в формате, специфичном для docbook, так что он не очень хорошо разработан.

На самом деле это еще не ответ на вопрос.Я все еще надеюсь, что где-то есть легко настраиваемый симпатичный принтер.

Ответы [ 4 ]

3 голосов
/ 14 марта 2013

Мое решение состояло в том, чтобы заменить pprint.PrettyPrinter простой оберткой, которая форматирует все найденные плавающие объекты перед вызовом оригинального принтера.

from __future__ import division
import pprint
if not hasattr(pprint,'old_printer'):
    pprint.old_printer=pprint.PrettyPrinter

class MyPrettyPrinter(pprint.old_printer):
    def _format(self,obj,*args,**kwargs):
        if isinstance(obj,float):
            obj=round(obj,4)
        return pprint.old_printer._format(self,obj,*args,**kwargs)
pprint.PrettyPrinter=MyPrettyPrinter

def pp(obj):
    pprint.pprint(obj)

if __name__=='__main__':
    x=[1,2,4,6,457,3,8,3,4]
    x=[_/17 for _ in x]
    pp(x)
2 голосов
/ 26 сентября 2018

Если вы хотите изменить красивый принтер по умолчанию без подклассов, вы можете использовать внутреннюю таблицу _dispatch в классе pprint.PrettyPrinter.Вы можете увидеть, как примеры добавления диспетчеризации для внутренних типов, таких как словари и списки в источнике .

Вот как я добавил собственный симпатичный принтер для Операции MatchPy тип:

import pprint
import matchpy

def _pprint_operation(self, object, stream, indent, allowance, context, level):
    """
    Modified from pprint dict https://github.com/python/cpython/blob/3.7/Lib/pprint.py#L194
    """
    operands = object.operands
    if not operands:
        stream.write(repr(object))
        return
    cls = object.__class__
    stream.write(cls.__name__ + "(")
    self._format_items(
        operands, stream, indent + len(cls.__name__), allowance + 1, context, level
    )
    stream.write(")")


pprint.PrettyPrinter._dispatch[matchpy.Operation.__repr__] = _pprint_operation

Теперь, если я использую pprint.pprint для любого объекта с таким же __repr__ как matchpy.Operation, он будет использовать этот метод для красивой печати.Это работает и для подклассов, если они не переопределяют __repr__, что имеет некоторый смысл!Если у вас тот же __repr__, то у вас такое же симпатичное поведение при печати. ​​

Вот пример симпатичной печати некоторых операций MatchPy сейчас:

ReshapeVector(Vector(Scalar('1')),
              Vector(Index(Vector(Scalar('0')),
                           If(Scalar('True'),
                              Scalar("ReshapeVector(Vector(Scalar('2'), Scalar('2')), Iota(Scalar('10')))"),
                              Scalar("ReshapeVector(Vector(Scalar('2'), Scalar('2')), Ravel(Iota(Scalar('10'))))")))))
2 голосов
/ 26 апреля 2011

Этот вопрос может быть повторен:


Использование pprint.PrettyPrinter

Я просмотрел источник pprint . Похоже, что для улучшения pprint() вам необходимо:

  • подкласс PrettyPrinter
  • переопределить _format()
  • тест для issubclass(),
  • и (если это не ваш класс) вернитесь к _format()

Альтернативный

Я думаю, что лучшим подходом было бы просто иметь свой собственный pprint(), что означает pprint.pformat, когда он не знает, что случилось.

Например:

'''Extending pprint'''

from pprint import pformat

class CrazyClass: pass

def prettyformat(obj):
    if isinstance(obj, CrazyClass):
        return "^CrazyFoSho^"
    else:
        return pformat(obj)

def prettyp(obj):
    print(prettyformat(obj))

# test
prettyp([1]*100)
prettyp(CrazyClass())

Большой плюс в том, что вы не зависите от pprint внутренних органов. Это ясно и кратко.

Недостатком является то, что вам придется заботиться о отступе вручную.

1 голос
/ 27 июля 2012

Рассмотрите возможность использования модуля pretty:

...