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,這會自動對字典的鍵進行排序。您可能更希望使用預設值為 Falsepp()

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__ 的子類)可防止遞迴。如果物件的表示暴露了遞迴入口,則遞迴引用將表示為 <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.org/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': 'pypa-dev@googlegroups.com',
 '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.org/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.org/project/sampleproject/',
 'project_urls': {'Download': 'UNKNOWN',
                  'Homepage': 'https://github.com/pypa/sampleproject'},
 'release_url': 'https://pypi.org/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': 'pypa-dev@googlegroups.com',
 '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.org/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.org/project/sampleproject/',
 'project_urls': {...},
 'release_url': 'https://pypi.org/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': 'pypa-dev@googlegroups.com',
 '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.org/project/sampleproject/',
 'platform': 'UNKNOWN',
 'project_url': 'https://pypi.org/project/sampleproject/',
 'project_urls': {...},
 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/',
 'requires_dist': None,
 'requires_python': None,
 'summary': 'A sample Python project',
 'version': '1.2.0'}