24

定制pprint.PrettyPrinter

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

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

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

备择方案?

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

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

为什么我要研究漂亮的印刷品

我的最终目标是紧凑地打印 DocBook-formatted 的自定义格式部分xml.etree.ElementTree

(我很惊讶没有找到对 DocBook 的更多 Python 支持。也许我在那里遗漏了一些东西。)

我在使用lxml的名为xmlearn的客户端中构建了一些基本功能。例如,要转储 Docbook 文件,您可以:

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

这很糟糕,但它让我得到了我正在寻找的信息。

xmlearn还具有其他功能,例如能够构建图形图像并进行转储以显示 XML 文档中标签之间的关系。这些与这个问题几乎完全无关。

您还可以将转储执行到任意深度,或者将 XPath 指定为一组起点。XPath 的东西有点过时了特定于 docbook 的格式,所以它并没有真正得到很好的开发。

这仍然不是这个问题的真正答案。我仍然希望在某个地方有一台易于定制的漂亮打印机。

4

4 回答 4

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)
于 2013-03-14T18:46:34.377 回答
2

这个问题可能与以下问题重复:


使用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内部。它明确而简洁。

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

于 2011-04-26T14:33:52.077 回答
2

如果您想修改默认的漂亮打印机而不进行子类化,您可以使用类_dispatch上的内部表pprint.PrettyPrinter您可以在源代码中查看如何为内部类型(如字典和列表)添加调度的示例。

以下是我为MatchPy 的 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'))))")))))
于 2018-09-26T15:50:03.823 回答
1

考虑使用该pretty模块:

于 2012-07-27T19:17:46.077 回答