pprint —- 数据美化输出

源代码: Lib/pprint.py [https://github.com/python/cpython/tree/3.13/Lib/pprint.py]


pprint 模块提供了“美化打印”任意 Python 数据结构的功能,这种美化形式可用作对解释器的输入。 如果经格式化的结构包含非基本 Python 类型的对象,则其美化形式可能无法被加载。 包含文件、套接字或类对象,以及许多其他不能用 Python 字面值来表示的对象都有可能导致这样的结果。

已格式化的表示形式会在可能的情况下将对象放在单行中,而当它们不能在允许宽度中被容纳时将其分为多行,允许宽度可由默认为 80 个字符的 width 形参加以调整。

字典在计算其显示形式前会先根据键来排序。

在 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 (file-like object | None) — 一个文件型对象,可通过调用其 write() 方法将输出写入该对象。 如为 None (默认值 ),则使用 sys.stdout

      • indent (int) — 要为每个嵌套层级添加的缩进量。

      • width (int) — 输出中每行所允许的最大字符数。 如果一个结构无法在宽度限制内被格式化,则将尽可能的接近。

      • depth (int | None) — 可被找钱的嵌套层级数量。 如果要打印的数据结构具有过深的层级,则其包含的下一层级将用 替换。 如为 None (默认值),则不会限制被格式化对象的层级深度。

      • compact (bool) — 控制长 序列 的格式化方式。 如为 False (默认值),则序列的每一项将被格式化为单独的行,否则在格式化每个输出行时将根据 width 限制容纳尽可能多的条目。

      • sort_dicts (bool) — 如为 True,则在格式化字典时将基于键进行排序,否则将按插入顺序显示它们(默认)。

      • underscorenumbers (bool) — 如为 True,则在格式化整数时将使用 \ 字符作为千位分隔符,否则将不显示下划线(默认)。

  1. >>> import pprint
  2. >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
  3. >>> stuff.insert(0, stuff)
  4. >>> pprint.pp(stuff)
  5. [<Recursion on list with id=...>,
  6. 'spam',
  7. 'eggs',
  8. 'lumberjack',
  9. 'knights',
  10. 'ni']

Added in version 3.8.

  • pprint.pprint(object, stream=None, indent=1, width=80, depth=None, *, compact=False, sort_dicts=True, underscore_numbers=False)
  • 默认将 sort_dicts 设为 Truepp() 的别名,它将自动按字典的键进行排序,你也可以选择使用该参数默认为 Falsepp()
  • pprint.pformat(object, indent=1, width=80, depth=None, *, compact=False, sort_dicts=True, underscore_numbers=False)
  • 将 object 的格式化表示形式作为字符串返回。 indent, width, depth, compact, sort_dicts 和 underscore_numbers 将作为格式化形参传递给 PrettyPrinter 构造器,它们的含义请参阅前面文档中的说明。
  • pprint.isreadable(object)
  • 确定 object 的格式化表示是否“可读”,或是否可被用来通过 eval() 重新构建对象的值。 此函数对于递归对象总是返回 False
  1. >>> pprint.isreadable(stuff)
  2. False
  • pprint.isrecursive(object)
  • 确定 object 是否需要递归的表示。 此函数会受到下面 saferepr() 所提及的同样限制的影响并可能在无法检测到可递归对象时引发 RecursionError
  • pprint.saferepr(object)
  • 返回 object 的字符串表示,并为某些通用数据结构提供防递归保护,包括 dict, listtuple 或其未重载 __repr__ 的子类的实例。 如果该对象表示形式公开了一个递归条目,该递归引用会被表示为 。 否则该表示形式将不会被格式化。
  1. >>> pprint.saferepr(stuff)
  2. "[<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

  1. >>> import pprint
  2. >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
  3. >>> stuff.insert(0, stuff[:])
  4. >>> pp = pprint.PrettyPrinter(indent=4)
  5. >>> pp.pprint(stuff)
  6. [ ['spam', 'eggs', 'lumberjack', 'knights', 'ni'],
  7. 'spam',
  8. 'eggs',
  9. 'lumberjack',
  10. 'knights',
  11. 'ni']
  12. >>> pp = pprint.PrettyPrinter(width=41, compact=True)
  13. >>> pp.pprint(stuff)
  14. [['spam', 'eggs', 'lumberjack',
  15. 'knights', 'ni'],
  16. 'spam', 'eggs', 'lumberjack', 'knights',
  17. 'ni']
  18. >>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead',
  19. ... ('parrot', ('fresh fruit',))))))))
  20. >>> pp = pprint.PrettyPrinter(depth=6)
  21. >>> pp.pprint(tup)
  22. ('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。 如果设置了 PrettyPrinter 的 depth 形参并且对象深度超出允许范围,此方法将返回 False
  • PrettyPrinter.isrecursive(object)
  • 确定对象是否需要递归表示。

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

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

示例

为了演示To demonstrate several uses of the pp() 函数及其形参的几种用法,让我们从 PyPI [https://pypi.org] 获取关于某个项目的信息:

  1. >>> import json
  2. >>> import pprint
  3. >>> from urllib.request import urlopen
  4. >>> with urlopen('https://pypi.org/pypi/sampleproject/1.2.0/json') as resp:
  5. ... project_info = json.load(resp)['info']

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

  1. >>> pprint.pp(project_info)
  2. {'author': 'The Python Packaging Authority',
  3. 'author_email': 'pypa-dev@googlegroups.com',
  4. 'bugtrack_url': None,
  5. 'classifiers': ['Development Status :: 3 - Alpha',
  6. 'Intended Audience :: Developers',
  7. 'License :: OSI Approved :: MIT License',
  8. 'Programming Language :: Python :: 2',
  9. 'Programming Language :: Python :: 2.6',
  10. 'Programming Language :: Python :: 2.7',
  11. 'Programming Language :: Python :: 3',
  12. 'Programming Language :: Python :: 3.2',
  13. 'Programming Language :: Python :: 3.3',
  14. 'Programming Language :: Python :: 3.4',
  15. 'Topic :: Software Development :: Build Tools'],
  16. 'description': 'A sample Python project\n'
  17. '=======================\n'
  18. '\n'
  19. 'This is the description file for the project.\n'
  20. '\n'
  21. 'The file should use UTF-8 encoding and be written using '
  22. 'ReStructured Text. It\n'
  23. 'will be used to generate the project webpage on PyPI, and '
  24. 'should be written for\n'
  25. 'that purpose.\n'
  26. '\n'
  27. 'Typical contents for this file would include an overview of '
  28. 'the project, basic\n'
  29. 'usage examples, etc. Generally, including the project '
  30. 'changelog in here is not\n'
  31. 'a good idea, although a simple "What\'s New" section for the '
  32. 'most recent version\n'
  33. 'may be appropriate.',
  34. 'description_content_type': None,
  35. 'docs_url': None,
  36. 'download_url': 'UNKNOWN',
  37. 'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1},
  38. 'home_page': 'https://github.com/pypa/sampleproject',
  39. 'keywords': 'sample setuptools development',
  40. 'license': 'MIT',
  41. 'maintainer': None,
  42. 'maintainer_email': None,
  43. 'name': 'sampleproject',
  44. 'package_url': 'https://pypi.org/project/sampleproject/',
  45. 'platform': 'UNKNOWN',
  46. 'project_url': 'https://pypi.org/project/sampleproject/',
  47. 'project_urls': {'Download': 'UNKNOWN',
  48. 'Homepage': 'https://github.com/pypa/sampleproject'},
  49. 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
  50. 'requires_dist': None,
  51. 'requires_python': None,
  52. 'summary': 'A sample Python project',
  53. 'version': '1.2.0'}

结果可以被限制到特定的 depth (更深层的内容将使用省略号):

  1. >>> pprint.pp(project_info, depth=1)
  2. {'author': 'The Python Packaging Authority',
  3. 'author_email': 'pypa-dev@googlegroups.com',
  4. 'bugtrack_url': None,
  5. 'classifiers': [...],
  6. 'description': 'A sample Python project\n'
  7. '=======================\n'
  8. '\n'
  9. 'This is the description file for the project.\n'
  10. '\n'
  11. 'The file should use UTF-8 encoding and be written using '
  12. 'ReStructured Text. It\n'
  13. 'will be used to generate the project webpage on PyPI, and '
  14. 'should be written for\n'
  15. 'that purpose.\n'
  16. '\n'
  17. 'Typical contents for this file would include an overview of '
  18. 'the project, basic\n'
  19. 'usage examples, etc. Generally, including the project '
  20. 'changelog in here is not\n'
  21. 'a good idea, although a simple "What\'s New" section for the '
  22. 'most recent version\n'
  23. 'may be appropriate.',
  24. 'description_content_type': None,
  25. 'docs_url': None,
  26. 'download_url': 'UNKNOWN',
  27. 'downloads': {...},
  28. 'home_page': 'https://github.com/pypa/sampleproject',
  29. 'keywords': 'sample setuptools development',
  30. 'license': 'MIT',
  31. 'maintainer': None,
  32. 'maintainer_email': None,
  33. 'name': 'sampleproject',
  34. 'package_url': 'https://pypi.org/project/sampleproject/',
  35. 'platform': 'UNKNOWN',
  36. 'project_url': 'https://pypi.org/project/sampleproject/',
  37. 'project_urls': {...},
  38. 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
  39. 'requires_dist': None,
  40. 'requires_python': None,
  41. 'summary': 'A sample Python project',
  42. 'version': '1.2.0'}

此外,还可以设置建议的最大字符 width。 如果一个对象无法被拆分,则将超出指定宽度:

  1. >>> pprint.pp(project_info, depth=1, width=60)
  2. {'author': 'The Python Packaging Authority',
  3. 'author_email': 'pypa-dev@googlegroups.com',
  4. 'bugtrack_url': None,
  5. 'classifiers': [...],
  6. 'description': 'A sample Python project\n'
  7. '=======================\n'
  8. '\n'
  9. 'This is the description file for the '
  10. 'project.\n'
  11. '\n'
  12. 'The file should use UTF-8 encoding and be '
  13. 'written using ReStructured Text. It\n'
  14. 'will be used to generate the project '
  15. 'webpage on PyPI, and should be written '
  16. 'for\n'
  17. 'that purpose.\n'
  18. '\n'
  19. 'Typical contents for this file would '
  20. 'include an overview of the project, '
  21. 'basic\n'
  22. 'usage examples, etc. Generally, including '
  23. 'the project changelog in here is not\n'
  24. 'a good idea, although a simple "What\'s '
  25. 'New" section for the most recent version\n'
  26. 'may be appropriate.',
  27. 'description_content_type': None,
  28. 'docs_url': None,
  29. 'download_url': 'UNKNOWN',
  30. 'downloads': {...},
  31. 'home_page': 'https://github.com/pypa/sampleproject',
  32. 'keywords': 'sample setuptools development',
  33. 'license': 'MIT',
  34. 'maintainer': None,
  35. 'maintainer_email': None,
  36. 'name': 'sampleproject',
  37. 'package_url': 'https://pypi.org/project/sampleproject/',
  38. 'platform': 'UNKNOWN',
  39. 'project_url': 'https://pypi.org/project/sampleproject/',
  40. 'project_urls': {...},
  41. 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
  42. 'requires_dist': None,
  43. 'requires_python': None,
  44. 'summary': 'A sample Python project',
  45. 'version': '1.2.0'}