> 技术文档 > 【Python】pprint 模块:以人类易读的方式格式化输出复杂的数据结构(如嵌套字典、列表)

【Python】pprint 模块:以人类易读的方式格式化输出复杂的数据结构(如嵌套字典、列表)

pprint 是 Python 标准库中的模块,全称 “pretty print”,用于格式化输出复杂的数据结构(如字典、列表、嵌套对象),使其更易读。与内置的 print 函数相比,pprint 提供更好的排版,自动添加换行和缩进,尤其适合调试或展示嵌套数据结构。pprint 模块简单易用,广泛用于开发、数据分析和日志记录。

以下是对 pprint 库的详细介绍,包括其功能、用法和实际应用。


1. pprint 库的作用

  • 格式化输出:以人类可读的方式打印复杂数据结构(如嵌套字典、列表)。
  • 自动缩进:为嵌套层级添加适当的缩进和换行。
  • 控制输出:支持自定义宽度、深度、排序等选项。
  • 调试友好:清晰展示数据结构,便于检查内容。
  • 标准库内置:无需额外安装,适合任何 Python 项目。

2. 安装与环境要求

  • Python 版本:内置于 Python 标准库(Python 2.x 和 3.x 均支持)。
  • 依赖:无外部依赖。
  • 导入方式
    from pprint import pprint
  • 验证可用性
    import pprintprint(pprint.__name__) # 输出: pprint

3. 核心功能与用法

pprint 模块的核心是通过 pprint() 函数或 PrettyPrinter 类格式化输出数据。以下是主要功能和示例

3.1 基本使用(pprint 函数)

使用 pprint() 格式化打印数据结构。

from pprint import pprintdata = { \"name\": \"Alice\", \"age\": 30, \"hobbies\": [\"reading\", \"gaming\"], \"address\": { \"street\": \"123 Main St\", \"city\": \"Wonderland\", \"coords\": {\"lat\": 40.7128, \"lon\": -74.0060} }}# 普通 printprint(data)# 使用 pprintpprint(data)

输出对比

  • print 输出(单行,难以阅读):
    {\'name\': \'Alice\', \'age\': 30, \'hobbies\': [\'reading\', \'gaming\'], \'address\': {\'street\': \'123 Main St\', \'city\': \'Wonderland\', \'coords\': {\'lat\': 40.7128, \'lon\': -74.0060}}}
  • pprint 输出(格式化,易读):
    {\'address\': {\'city\': \'Wonderland\', \'coords\': {\'lat\': 40.7128, \'lon\': -74.006}, \'street\': \'123 Main St\'}, \'age\': 30, \'hobbies\': [\'reading\', \'gaming\'], \'name\': \'Alice\'}

说明

  • pprint 自动为嵌套结构添加换行和缩进。
  • 默认宽度为 80 字符,自动折行。
3.2 控制输出格式

pprint() 支持多个参数自定义输出。

from pprint import pprintdata = {\"a\": [1, 2, 3], \"b\": {\"x\": 10, \"y\": 20}, \"c\": \"text\"}# 自定义宽度和缩进pprint(data, width=50, indent=2)# 限制嵌套深度pprint(data, depth=1)# 排序字典键pprint(data, sort_dicts=True)

输出示例

  • width=50, indent=2
    { \'a\': [1, 2, 3], \'b\': {\'x\': 10, \'y\': 20}, \'c\': \'text\'}
  • depth=1
    {\'a\': [...], \'b\': {...}, \'c\': \'text\'}
  • sort_dicts=True
    {\'a\': [1, 2, 3], \'b\': {\'x\': 10, \'y\': 20}, \'c\': \'text\'}

说明

  • width:控制每行最大字符数。
  • indent:设置缩进空格数。
  • depth:限制显示的嵌套层级,超出部分显示为 ...
  • sort_dicts(Python 3.8+):是否按键排序字典(默认 False)。
3.3 PrettyPrinter 类

使用 PrettyPrinter 类创建自定义打印器,复用配置。

from pprint import PrettyPrinter# 创建自定义打印器pp = PrettyPrinter(width=40, indent=2, sort_dicts=True)data = {\"a\": [1, 2, 3], \"b\": {\"x\": 10, \"y\": 20}, \"c\": \"text\"}pp.pprint(data)

输出示例

{ \'a\': [1, 2, 3], \'b\': { \'x\': 10, \'y\': 20}, \'c\': \'text\'}

说明

  • PrettyPrinter 适合需要一致格式的场景。
  • 支持与 pprint() 相同的参数。
3.4 格式化为字符串

使用 pformat 返回格式化字符串,而不是直接打印。

from pprint import pformatdata = {\"a\": [1, 2, 3], \"b\": {\"x\": 10, \"y\": 20}}formatted = pformat(data, width=50)print(f\"Formatted data:\\n{formatted}\")

输出示例

Formatted data:{\'a\': [1, 2, 3], \'b\': {\'x\': 10, \'y\': 20}}

说明

  • pformat 返回字符串,适合日志记录或进一步处理。
  • 支持与 pprint 相同的参数。
3.5 处理自定义对象

pprint 默认格式化内置类型,自定义对象需实现 __repr__

from pprint import pprintclass Person: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f\"Person(name={self.name!r}, age={self.age})\"data = [Person(\"Alice\", 30), Person(\"Bob\", 25)]pprint(data)

输出示例

[Person(name=\'Alice\', age=30), Person(name=\'Bob\', age=25)]

说明

  • 自定义 __repr__ 控制对象在 pprint 中的显示。
  • 避免使用 __str__,因为 pprint 优先调用 __repr__
3.6 流控制

将输出写入文件或自定义流。

from pprint import pprintimport sysdata = {\"a\": [1, 2, 3], \"b\": {\"x\": 10, \"y\": 20}}# 输出到文件with open(\"output.txt\", \"w\") as f: pprint(data, stream=f)# 输出到标准错误pprint(data, stream=sys.stderr)

说明

  • stream 参数指定输出目标(如文件或 sys.stderr)。
  • 默认 stream=None,输出到 sys.stdout

4. 性能与特点

  • 高效性:对中小型数据结构,格式化速度快。
  • 易用性:无需配置,开箱即用。
  • 灵活性:支持宽度、深度、缩进等自定义选项。
  • 局限性
    • 超大数据结构(数千嵌套层级)可能导致性能下降。
    • 不支持颜色高亮或复杂格式化(如 JSON 着色)。
  • 跨版本兼容
    • Python 2.x 和 3.x 均支持,3.8+ 增加 sort_dicts 参数。
    • 标准库,无兼容性问题。

5. 实际应用场景

  • 调试:打印复杂数据结构(如 API 响应、配置字典)。
  • 数据分析:格式化 Pandas DataFrame 或 NumPy 数组。
  • 日志记录:使用 pformat 将数据结构写入日志。
  • API 开发:展示 JSON 响应或请求体。
  • 教学与文档:生成易读的输出,用于演示或说明。

示例(与 FastAPI 集成)

from fastapi import FastAPIfrom pprint import pformatfrom loguru import loggerapp = FastAPI()@app.get(\"/data\")async def get_data(): data = { \"users\": [ {\"id\": 1, \"name\": \"Alice\", \"roles\": [\"admin\", \"user\"]}, {\"id\": 2, \"name\": \"Bob\", \"roles\": [\"user\"]} ], \"settings\": {\"debug\": True, \"version\": \"1.0\"} } # 记录格式化数据 logger.info(f\"Response data:\\n{pformat(data)}\") return data

输出示例(日志):

2025-05-09 12:34:56.123 | INFO | Response data:{\'settings\': {\'debug\': True, \'version\': \'1.0\'}, \'users\': [{\'id\': 1, \'name\': \'Alice\', \'roles\': [\'admin\', \'user\']},  {\'id\': 2, \'name\': \'Bob\', \'roles\': [\'user\']}]}

说明

  • 使用 pformat 记录 API 响应,便于调试。

6. 与替代方案对比

  • print
    • 简单,但输出单行,复杂结构难以阅读。
    • 无格式化选项。
  • json.dumps
    import jsonprint(json.dumps(data, indent=2))
    • 适合 JSON 数据,提供缩进,但不支持非 JSON 序列化对象(如自定义类)。
    • 输出格式固定,缺少 pprint 的深度控制。
  • yaml.dump
    import yamlprint(yaml.dump(data))
    • 生成 YAML 格式,适合配置文件,但依赖外部库。
  • pprint 的优势
    • 内置标准库,无需额外安装。
    • 灵活控制输出(宽度、深度、排序)。
    • 支持任意 Python 对象(通过 __repr__)。

7. 注意事项

  • 性能
    • 超大数据结构可能导致格式化缓慢,建议限制 depth
      pprint(large_data, depth=2)
    • 对于简单数据,print 可能更快。
  • 输出控制
    • 默认宽度 80 字符,可能导致意外折行,调整 width
      pprint(data, width=120)
    • 深度限制(depth)适合快速预览复杂对象。
  • 自定义对象
    • 确保自定义类实现 __repr__,否则输出可能是
  • Python 版本
    • Python 3.8+ 支持 sort_dicts,旧版本字典顺序随机。
    • Python 2.x 的 pprint 功能略少,但基本兼容。
  • 替代工具
    • 对于 JSON 数据,json.dumps(indent=2) 更轻量。
    • 对于彩色输出,结合 rich 库:
      from rich import print as rprintrprint(data)

8. 综合示例

以下是一个综合示例,展示 pprint 在调试、日志记录和自定义对象中的使用:

from pprint import pprint, pformat, PrettyPrinterfrom loguru import loggerimport sys# 自定义类class Employee: def __init__(self, name, id, skills): self.name = name self.id = id self.skills = skills def __repr__(self): return f\"Employee(name={self.name!r}, id={self.id}, skills={self.skills!r})\"# 示例数据data = { \"company\": \"Tech Corp\", \"employees\": [ Employee(\"Alice\", 1, [\"Python\", \"SQL\"]), Employee(\"Bob\", 2, [\"Java\", \"Docker\"]), ], \"projects\": { \"AI\": {\"status\": \"active\", \"budget\": 100000}, \"Web\": {\"status\": \"planning\", \"budget\": 50000} }}# 基本打印print(\"Basic pprint:\")pprint(data, width=60)# 自定义打印器print(\"\\nCustom PrettyPrinter:\")pp = PrettyPrinter(width=50, indent=2, depth=2, stream=sys.stderr)pp.pprint(data)# 格式化为字符串并记录logger.add(\"app.log\", format=\"{time} | {level} | {message}\")logger.info(\"Data structure:\\n{}\", pformat(data, width=70))# 限制深度print(\"\\nDepth-limited output:\")pprint(data, depth=1)

输出示例

  • 终端(pprint):
    Basic pprint:{\'company\': \'Tech Corp\', \'employees\': [Employee(name=\'Alice\', id=1, skills=[\'Python\', \'SQL\']),  Employee(name=\'Bob\', id=2, skills=[\'Java\', \'Docker\'])], \'projects\': {\'AI\': {\'budget\': 100000, \'status\': \'active\'},  \'Web\': {\'budget\': 50000, \'status\': \'planning\'}}}Custom PrettyPrinter:{ \'company\': \'Tech Corp\', \'employees\': [...], \'projects\': {...}}Depth-limited output:{\'company\': \'Tech Corp\', \'employees\': [...], \'projects\': {...}}
  • 日志(app.log):
    2025-05-09T12:34:56.123456 | INFO | Data structure:{\'company\': \'Tech Corp\', \'employees\': [Employee(name=\'Alice\', id=1, skills=[\'Python\', \'SQL\']),  Employee(name=\'Bob\', id=2, skills=[\'Java\', \'Docker\'])], \'projects\': {\'AI\': {\'budget\': 100000, \'status\': \'active\'},  \'Web\': {\'budget\': 50000, \'status\': \'planning\'}}}

说明

  • 展示不同宽度和深度的格式化输出。
  • 使用 PrettyPrinter 输出到 sys.stderr
  • 通过 pformat 记录日志。
  • 自定义 Employee 类的 __repr__ 确保清晰输出。

9. 资源与文档

  • 官方文档:https://docs.python.org/3/library/pprint.html
  • Python 标准库pprint 源代码可在 Python 源码中查看。
  • 教程
    • Real Python 的 pprint 指南:https://realpython.com/python-pretty-print/
    • Python 官方 pprint 示例:https://docs.python.org/3/library/pprint.html#module-pprint