实现自定义漂亮打印机的最佳方式

时间:2010-07-15 17:08:19

标签: python xml subclass pretty-print docbook

自定义pprint.PrettyPrinter

pprint模块的文档提到方法PrettyPrinter.format旨在使自定义格式化成为可能。

我认为可以在子类中覆盖此方法,但这似乎没有提供让基类方法应用换行和缩进的方法。

  • 我在这里错过了什么吗?
  • 有没有更好的方法(例如另一个模块)?

替代?

我已经检查了pretty模块,它看起来很有趣,但似乎没有提供一种方法来自定义其他模块的类格式而不修改这些模块。

我认为我正在寻找的是允许我提供类型(或可能是函数)的映射,这些类型可以识别处理节点的例程的类型。处理节点的例程将获取一个节点并返回它的字符串表示以及子节点列表。等等。

为什么我要研究漂亮的打印

我的最终目标是紧凑打印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 个答案:

答案 0 :(得分:3)

我的解决方案是用一个简单的包装器替换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)

答案 1 :(得分:2)

此问题可能与以下内容重复:


使用pprint.PrettyPrinter

我浏览了source of 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内部。它明确而简洁。

缺点是您必须手动处理缩进。

答案 2 :(得分:2)

如果要在不进行子类化的情况下修改默认的漂亮打印机,则可以使用_dispatch类上的内部pprint.PrettyPrinter表。您可以看到如何为字典和列表in the source等内部类型添加调度的示例。

这是我为MatchPy's Operation类型添加自定义漂亮打印机的方式:

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'))))")))))

答案 3 :(得分:1)

考虑使用pretty模块: