精美的印刷

除了语法突出显示外,Rich还将格式化(即 pretty print )容器,如列表、词典和集合。

运行以下命令以查看打印输出的示例:

python -m rich.pretty

请注意,输出将如何更改以适应终端宽度。

Pprint方法

这个 pprint() 方法提供了更多的参数,您可以使用它们来调整对象的打印方式。以下是导入它的方法::

>>> from rich.pretty import pprint
>>> pprint(locals())

缩进辅助线

里奇会画画 indent guides 以突出显示数据结构的缩进级别。这些可以使读取嵌套更深的输出变得更容易。默认情况下,pprint方法启用缩进辅助线。您可以设置 indent_guides=False 以禁用此功能。

全部展开

Rich在扩展数据结构方面相当保守,并将尝试尽可能多地适应每一行。如果愿意,您可以告诉Rich通过设置来完全扩展所有数据结构 expand_all=True 。以下是一个示例:

>>> pprint(["eggs", "ham"], expand_all=True)

截断相当不错的产出

很长的数据结构可能很难阅读,您可能会发现自己在终端的多个页面中滚动以找到您感兴趣的数据。Rich可以截断容器和长字符串,为您提供概述,而不会淹没您的码头。

如果您将 max_length argument to an integer, Rich will truncate containers with more than the given number of elements. If data is truncated, Rich will display an ellipsis ... 以及未显示的元素的数量。

以下是一个示例:

>>> pprint(locals(), max_length=2)

如果您将 max_string 参数设置为整数,则Rich将截断该长度的字符串。截断的字符串将追加未显示的字符数。以下是一个示例:

>>> pprint("Where there is a Will, there is a Way", max_string=21)

渲染效果非常好

Rich提供了一种 Pretty 类,您可以使用该类将精美的打印数据插入到另一个可呈现的。

下面的示例在一个简单的面板中显示漂亮的打印数据:

from rich import print
from rich.pretty import Pretty
from rich.panel import Panel

pretty = Pretty(locals())
panel = Panel(pretty)
print(panel)

有大量选项可以调整漂亮的格式,请参阅 Pretty 有关详情,请参阅。

富REPR协议

Rich能够在语法上突出显示任何输出,但格式化仅限于内置容器、数据类和Rich知道的其他对象,例如由 attrs 类库。若要向自定义对象添加丰富的格式设置功能,可以实现 rich repr protocol

运行以下命令以查看Rich Repr协议可以生成的示例:

python -m rich.repr

首先,让我们看一个可能受益于Rich Repr::

class Bird:
    def __init__(self, name, eats=None, fly=True, extinct=False):
        self.name = name
        self.eats = list(eats) if eats else []
        self.fly = fly
        self.extinct = extinct

    def __repr__(self):
        return f"Bird({self.name!r}, eats={self.eats!r}, fly={self.fly!r}, extinct={self.extinct!r})"

BIRDS = {
    "gull": Bird("gull", eats=["fish", "chips", "ice cream", "sausage rolls"]),
    "penguin": Bird("penguin", eats=["fish"], fly=False),
    "dodo": Bird("dodo", eats=["fruit"], fly=False, extinct=True)
}
print(BIRDS)

此脚本的结果将是::

{'gull': Bird('gull', eats=['fish', 'chips', 'ice cream', 'sausage rolls'], fly=True, extinct=False), 'penguin': Bird('penguin', eats=['fish'], fly=False, extinct=False), 'dodo': Bird('dodo', eats=['fruit'], fly=False, extinct=True)}

输出足够长,可以换到下一行,这可能会使其难以阅读。REPR字符串是信息性的,但有点冗长,因为它们包含默认参数。如果我们与Rich一起打印,情况会有所改善::

{
    'gull': Bird('gull', eats=['fish', 'chips', 'ice cream', 'sausage rolls'],
fly=True, extinct=False),
    'penguin': Bird('penguin', eats=['fish'], fly=False, extinct=False),
    'dodo': Bird('dodo', eats=['fruit'], fly=False, extinct=True)
}

Rich知道如何格式化容器DICT,但是REPR字符串仍然很冗长,并且输出有一些换行(假设终端是80个字符)。

我们可以通过添加以下内容来解决这两个问题 __rich_repr__ 方法:

def __rich_repr__(self):
    yield self.name
    yield "eats", self.eats
    yield "fly", self.fly, True
    yield "extinct", self.extinct, False

现在,如果我们使用Rich打印相同的对象,我们将看到以下内容:

{
    'gull': Bird(
        'gull',
        eats=['fish', 'chips', 'ice cream', 'sausage rolls']
    ),
    'penguin': Bird('penguin', eats=['fish'], fly=False),
    'dodo': Bird('dodo', eats=['fruit'], fly=False, extinct=True)
}

省略了缺省参数,并且输出的格式设置得很好。即使我们在终端中的空间较小,或者我们的对象是深度嵌套的数据结构的一部分,输出仍可读:

{
    'gull': Bird(
        'gull',
        eats=[
            'fish',
            'chips',
            'ice cream',
            'sausage rolls'
        ]
    ),
    'penguin': Bird(
        'penguin',
        eats=['fish'],
        fly=False
    ),
    'dodo': Bird(
        'dodo',
        eats=['fruit'],
        fly=False,
        extinct=True
    )
}

您可以添加一个 __rich_repr__ 方法绑定到任何类以启用Rich Formatting。此方法应返回可迭代的元组。您可以返回元组列表,但使用 yield 关键字,使其成为 generator

每个元组指定输出中的一个元素。

  • yield value 将生成位置参数。

  • yield name, value 将生成关键字参数。

  • yield name, value, default 将生成关键字参数 if value 不等于 default

如果您使用 None 作为 name ,那么它也将被视为位置参数,以支持具有 tuple 立场论据。

您还可以告诉Rich生成 angular bracket 样式的REPR,通常用于没有简单的方法来重新创建对象的构造函数的地方。为此,请设置Function属性 "angular"True 紧接在您的 __rich_repr__ 方法。例如::

__rich_repr__.angular = True

这会将Rich epr示例的输出更改为以下内容:

{
    'gull': <Bird 'gull' eats=['fish', 'chips', 'ice cream', 'sausage rolls']>,
    'penguin': <Bird 'penguin' eats=['fish'] fly=False>,
    'dodo': <Bird 'dodo' eats=['fruit'] fly=False extinct=True>
}

请注意,您可以添加 __rich_repr__ 方法提供给第三方库 without 将Rich作为依附者包括在内。如果没有安装Rich,那么任何东西都不会损坏。希望未来会有更多的第三方库采用Rich Repr方法。

打字

如果要输入Rich epr方法,可以导入并返回 rich.repr.Result ,这将有助于捕获逻辑错误::

import rich.repr


class Bird:
    def __init__(self, name, eats=None, fly=True, extinct=False):
        self.name = name
        self.eats = list(eats) if eats else []
        self.fly = fly
        self.extinct = extinct

    def __rich_repr__(self) -> rich.repr.Result:
        yield self.name
        yield "eats", self.eats
        yield "fly", self.fly, True
        yield "extinct", self.extinct, False

自动丰富报告

如果参数的名称与您的属性相同,Rich可以自动生成一个丰富的REPR。

若要自动构建富REPR,请使用 auto() 班级装饰师。上面的Bird示例遵循上述规则,因此我们不需要严格地实现我们自己的 __rich_repr__ 。以下代码将生成相同的epr::

import rich.repr

@rich.repr.auto
class Bird:
    def __init__(self, name, eats=None, fly=True, extinct=False):
        self.name = name
        self.eats = list(eats) if eats else []
        self.fly = fly
        self.extinct = extinct


BIRDS = {
    "gull": Bird("gull", eats=["fish", "chips", "ice cream", "sausage rolls"]),
    "penguin": Bird("penguin", eats=["fish"], fly=False),
    "dodo": Bird("dodo", eats=["fruit"], fly=False, extinct=True)
}
from rich import print
print(BIRDS)

请注意,装饰器还将创建一个 __repr__ ,所以即使你不使用Rich打印,你也会得到一个自动生成的REPR。

如果您想要自动生成REPR的角度类型,则设置 angular=True 关于装潢::

@rich.repr.auto(angular=True)
class Bird:
    def __init__(self, name, eats=None, fly=True, extinct=False):
        self.name = name
        self.eats = list(eats) if eats else []
        self.fly = fly
        self.extinct = extinct

示例

看见 repr.py 获取本页中使用的示例代码。