pprint — 数据美化打印

源代码: Lib/pprint.py


pprint 模块提供了一种以可作为解释器输入的形式“美化打印”任意 Python 数据结构的功能。如果格式化的结构包含的不是基本的 Python 类型,则该表示形式可能无法加载。如果包含文件、套接字或类等对象,以及许多其他无法表示为 Python 字面量的对象,则可能会出现这种情况。

格式化表示形式会尽可能将对象放在同一行,如果对象不适合允许的宽度,则会将其拆分到多行,该宽度可通过 width 参数进行调整,默认为 80 个字符。

在计算显示之前,字典会按键排序。

在 3.9 版本中更改: 增加了对美化打印 types.SimpleNamespace 的支持。

在 3.10 版本中更改: 增加了对美化打印 dataclasses.dataclass 的支持。

函数

pprint.pp(object, stream=None, indent=1, width=80, depth=None, *, compact=False, sort_dicts=False, underscore_numbers=False)

打印 object 的格式化表示形式,后跟一个换行符。此函数可以在交互式解释器中代替 print() 函数用于检查值。提示:您可以在作用域内重新分配 print = pprint.pp 以便使用。

参数:
  • object – 要打印的对象。

  • stream (类文件对象 | None) – 一个类文件对象,将通过调用其 write() 方法将输出写入到该对象。如果为 None(默认值),则使用 sys.stdout

  • indent (int) – 每个嵌套级别添加的缩进量。

  • width (int) – 输出中每行所需的最多字符数。如果结构无法在宽度约束内格式化,则会尽最大努力进行格式化。

  • depth (int | None) – 可以打印的嵌套级别数。如果要打印的数据结构太深,则下一个包含的级别将被替换为 ...。如果为 None(默认值),则对格式化的对象的深度没有约束。

  • compact (bool) – 控制格式化长 序列 的方式。如果为 False(默认值),则序列的每个项目将在单独的行上格式化,否则,将在每行输出上格式化尽可能多的项目,以便适应 width

  • sort_dicts (bool) – 如果为 True,则字典将按键排序格式化,否则将按插入顺序显示(默认值)。

  • underscore_numbers (bool) – 如果为 True,则整数将使用 _ 字符作为千位分隔符格式化,否则不显示下划线(默认值)。

>>> import pprint
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
>>> stuff.insert(0, stuff)
>>> pprint.pp(stuff)
[<Recursion on list with id=...>,
 'spam',
 'eggs',
 'lumberjack',
 'knights',
 'ni']

在 3.8 版本中添加。

pprint.pprint(object, stream=None, indent=1, width=80, depth=None, *, compact=False, sort_dicts=True, underscore_numbers=False)

别名 pp(),其中 sort_dicts 默认设置为 True,这将自动对字典的键进行排序,您可能想要使用 pp(),其中默认值为 False

pprint.pformat(object, indent=1, width=80, depth=None, *, compact=False, sort_dicts=True, underscore_numbers=False)

以字符串形式返回 object 的格式化表示形式。indentwidthdepthcompactsort_dictsunderscore_numbers 作为格式化参数传递给 PrettyPrinter 构造函数,它们的含义如上述文档中所述。

pprint.isreadable(object)

确定 object 的格式化表示形式是否“可读”,或者是否可以使用 eval() 重构该值。对于递归对象,此函数始终返回 False

>>> pprint.isreadable(stuff)
False
pprint.isrecursive(object)

确定 object 是否需要递归表示。此函数受到与下面 saferepr() 中所述相同的限制,如果无法检测到递归对象,可能会引发 RecursionError

pprint.saferepr(object)

返回 object 的字符串表示形式,该表示形式针对一些常见数据结构(即 dictlisttuple 的实例或其 __repr__ 未被覆盖的子类)中的递归进行了保护。如果 object 的表示形式暴露了递归条目,则递归引用将表示为 <Recursion on typename with id=number>。该表示形式没有进行其他格式化。

>>> pprint.saferepr(stuff)
"[<Recursion on list with id=...>, 'spam', 'eggs', 'lumberjack', 'knights', 'ni']"

PrettyPrinter 对象

class pprint.PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, compact=False, sort_dicts=True, underscore_numbers=False)

构造一个 PrettyPrinter 实例。

参数的含义与 pp() 的含义相同。请注意,它们的顺序不同,并且 sort_dicts 默认为 True

>>> import pprint
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
>>> stuff.insert(0, stuff[:])
>>> pp = pprint.PrettyPrinter(indent=4)
>>> pp.pprint(stuff)
[   ['spam', 'eggs', 'lumberjack', 'knights', 'ni'],
    'spam',
    'eggs',
    'lumberjack',
    'knights',
    'ni']
>>> pp = pprint.PrettyPrinter(width=41, compact=True)
>>> pp.pprint(stuff)
[['spam', 'eggs', 'lumberjack',
  'knights', 'ni'],
 'spam', 'eggs', 'lumberjack', 'knights',
 'ni']
>>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead',
... ('parrot', ('fresh fruit',))))))))
>>> pp = pprint.PrettyPrinter(depth=6)
>>> pp.pprint(tup)
('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead', (...)))))))

在 3.4 版本中更改: 添加了 compact 参数。

在 3.8 版本中更改: 添加了 sort_dicts 参数。

在 3.10 版本中更改: 添加了 underscore_numbers 参数。

在 3.11 版本中更改: 如果 sys.stdoutNone,则不再尝试写入它。

PrettyPrinter 实例具有以下方法

PrettyPrinter.pformat(object)

返回 object 的格式化表示形式。这会考虑传递给 PrettyPrinter 构造函数的选项。

PrettyPrinter.pprint(object)

在配置的流上打印 object 的格式化表示形式,后跟换行符。

以下方法提供了同名对应函数的实现。在实例上使用这些方法效率稍高,因为不需要创建新的 PrettyPrinter 对象。

PrettyPrinter.isreadable(object)

确定对象的格式化表示形式是否“可读”,或者是否可以使用 eval() 重构该值。请注意,对于递归对象,这将返回 False。如果设置了 PrettyPrinterdepth 参数,并且对象比允许的深度更深,则这将返回 False

PrettyPrinter.isrecursive(object)

确定对象是否需要递归表示。

提供此方法作为钩子,以允许子类修改对象转换为字符串的方式。默认实现使用 saferepr() 实现的内部结构。

PrettyPrinter.format(object, context, maxlevels, level)

返回三个值:object 的格式化版本(字符串)、一个指示结果是否可读的标志以及一个指示是否检测到递归的标志。第一个参数是要呈现的对象。第二个参数是一个字典,其中包含作为键的当前呈现上下文(影响呈现的 object 的直接和间接容器)的一部分的对象的 id();如果需要呈现的对象已在 context 中表示,则第三个返回值应为 True。对 format() 方法的递归调用应将容器的其他条目添加到此字典中。第三个参数 maxlevels 给出了请求的递归限制;如果没有请求的限制,则此参数将为 0。此参数应不做修改地传递给递归调用。第四个参数 level 给出了当前级别;递归调用应传递一个小于当前调用的值。

示例

为了演示 pp() 函数及其参数的几种用法,让我们从 PyPI 获取有关项目的信息

>>> import json
>>> import pprint
>>> from urllib.request import urlopen
>>> with urlopen('https://pypi.ac.cn/pypi/sampleproject/1.2.0/json') as resp:
...     project_info = json.load(resp)['info']

在其基本形式中,pp() 显示整个对象

>>> pprint.pp(project_info)
{'author': 'The Python Packaging Authority',
 'author_email': '[email protected]',
 'bugtrack_url': None,
 'classifiers': ['Development Status :: 3 - Alpha',
                 'Intended Audience :: Developers',
                 'License :: OSI Approved :: MIT License',
                 'Programming Language :: Python :: 2',
                 'Programming Language :: Python :: 2.6',
                 'Programming Language :: Python :: 2.7',
                 'Programming Language :: Python :: 3',
                 'Programming Language :: Python :: 3.2',
                 'Programming Language :: Python :: 3.3',
                 'Programming Language :: Python :: 3.4',
                 'Topic :: Software Development :: Build Tools'],
 'description': 'A sample Python project\n'
                '=======================\n'
                '\n'
                'This is the description file for the project.\n'
                '\n'
                'The file should use UTF-8 encoding and be written using '
                'ReStructured Text. It\n'
                'will be used to generate the project webpage on PyPI, and '
                'should be written for\n'
                'that purpose.\n'
                '\n'
                'Typical contents for this file would include an overview of '
                'the project, basic\n'
                'usage examples, etc. Generally, including the project '
                'changelog in here is not\n'
                'a good idea, although a simple "What\'s New" section for the '
                'most recent version\n'
                'may be appropriate.',
 'description_content_type': None,
 'docs_url': None,
 'download_url': 'UNKNOWN',
 'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1},
 'home_page': 'https://github.com/pypa/sampleproject',
 'keywords': 'sample setuptools development',
 'license': 'MIT',
 'maintainer': None,
 'maintainer_email': None,
 'name': 'sampleproject',
 'package_url': 'https://pypi.ac.cn/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.ac.cn/project/sampleproject/',
 'project_urls': {'Download': 'UNKNOWN',
                  'Homepage': 'https://github.com/pypa/sampleproject'},
 'release_url': 'https://pypi.ac.cn/project/sampleproject/1.2.0/',
 'requires_dist': None,
 'requires_python': None,
 'summary': 'A sample Python project',
 'version': '1.2.0'}

结果可以限制为某个 depth (省略号用于更深的内容)

>>> pprint.pp(project_info, depth=1)
{'author': 'The Python Packaging Authority',
 'author_email': '[email protected]',
 'bugtrack_url': None,
 'classifiers': [...],
 'description': 'A sample Python project\n'
                '=======================\n'
                '\n'
                'This is the description file for the project.\n'
                '\n'
                'The file should use UTF-8 encoding and be written using '
                'ReStructured Text. It\n'
                'will be used to generate the project webpage on PyPI, and '
                'should be written for\n'
                'that purpose.\n'
                '\n'
                'Typical contents for this file would include an overview of '
                'the project, basic\n'
                'usage examples, etc. Generally, including the project '
                'changelog in here is not\n'
                'a good idea, although a simple "What\'s New" section for the '
                'most recent version\n'
                'may be appropriate.',
 'description_content_type': None,
 'docs_url': None,
 'download_url': 'UNKNOWN',
 'downloads': {...},
 'home_page': 'https://github.com/pypa/sampleproject',
 'keywords': 'sample setuptools development',
 'license': 'MIT',
 'maintainer': None,
 'maintainer_email': None,
 'name': 'sampleproject',
 'package_url': 'https://pypi.ac.cn/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.ac.cn/project/sampleproject/',
 'project_urls': {...},
 'release_url': 'https://pypi.ac.cn/project/sampleproject/1.2.0/',
 'requires_dist': None,
 'requires_python': None,
 'summary': 'A sample Python project',
 'version': '1.2.0'}

此外,可以建议最大字符 width。如果无法拆分长对象,则将超过指定的宽度

>>> pprint.pp(project_info, depth=1, width=60)
{'author': 'The Python Packaging Authority',
 'author_email': '[email protected]',
 'bugtrack_url': None,
 'classifiers': [...],
 'description': 'A sample Python project\n'
                '=======================\n'
                '\n'
                'This is the description file for the '
                'project.\n'
                '\n'
                'The file should use UTF-8 encoding and be '
                'written using ReStructured Text. It\n'
                'will be used to generate the project '
                'webpage on PyPI, and should be written '
                'for\n'
                'that purpose.\n'
                '\n'
                'Typical contents for this file would '
                'include an overview of the project, '
                'basic\n'
                'usage examples, etc. Generally, including '
                'the project changelog in here is not\n'
                'a good idea, although a simple "What\'s '
                'New" section for the most recent version\n'
                'may be appropriate.',
 'description_content_type': None,
 'docs_url': None,
 'download_url': 'UNKNOWN',
 'downloads': {...},
 'home_page': 'https://github.com/pypa/sampleproject',
 'keywords': 'sample setuptools development',
 'license': 'MIT',
 'maintainer': None,
 'maintainer_email': None,
 'name': 'sampleproject',
 'package_url': 'https://pypi.ac.cn/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.ac.cn/project/sampleproject/',
 'project_urls': {...},
 'release_url': 'https://pypi.ac.cn/project/sampleproject/1.2.0/',
 'requires_dist': None,
 'requires_python': None,
 'summary': 'A sample Python project',
 'version': '1.2.0'}