pprint --- 數據美化輸出?

源代碼: Lib/pprint.py


pprint 模塊提供了“美化打印”任意 Python 數據結構的功能,這種美化形式可用作對解釋器的輸入。 如果經格式化的結構包含非基本 Python 類型的對象,則其美化形式可能無法被加載。 包含文件、套接字或類對象,以及許多其他不能用 Python 字面值來表示的對象都有可能導致這樣的結果。

格式化后的形式會在可能的情況下以單行來表示對象,并在無法在允許寬度內容納對象的情況下將其分為多行。 如果你需要調整寬度限制則應顯式地構造 PrettyPrinter 對象。

Dictionaries are sorted by key before the display is computed. 字典在被計算前通過鍵值來排序。

pprint 模塊定義了一個類:

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

構造一個 PrettyPrinter 實例。 此構造器接受幾個關鍵字形參。 使用 stream 關鍵字可設置輸出流;在流對象上使用的唯一方法是文件協議的 write() 方法。 如果未指定此關鍵字,則 PrettyPrinter 會選擇 sys.stdout。 每個遞歸層級的縮進量由 indent 指定;默認值為一。 其他值可導致輸出看起來有些怪異,但可使得嵌套結構更易區分。 可被打印的層級數量由 depth 控制;如果數據結構的層級被打印得過深,其所包含的下一層級會被替換為 ...。 在默認情況下,對被格式化對象的層級深度沒有限制。 希望的輸出寬度可使用 width 形參來限制;默認值為 80 個字符。 如果一個結構無法在限定寬度內被格式化,則將做到盡可能接近。 如果 compact 為假值(默認)則長序列的每一項將被格式化為單獨的行。 如果 compact 為真值,則格式化將在 width 可容納的情況下把盡可能多的項放入每個輸出行。

在 3.4 版更改: 加入*compact* 參數。

>>> 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', (...)))))))

pprint 模塊還提供了一些快捷函數:

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

object 格式化表示作為字符串返回。 indent, width, depthcompact 將作為格式化形參被傳入 PrettyPrinter 構造器。

在 3.4 版更改: 加入*compact* 參數。

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

stream 上打印 object 的格式化表示,并附帶一個換行符。 如果 streamNone,則使用 sys.stdout。 這可以替換 print() 函數在交互式解釋器中使用以查看值(你甚至可以執行重新賦值 print = pprint.pprint 以在特定作用域中使用)。 indent, width, depthcompact 將作為格式化形參被傳給 PrettyPrinter 構造器。

在 3.4 版更改: 加入*compact* 參數。

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

確定 object 的格式化表示是否“可讀”,或是否可被用來通過 eval() 重新構建對象的值。 此函數對于遞歸對象總是返回 False

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

確定 object 是否需要遞歸表示。

此外還定義了一個支持函數:

pprint.saferepr(object)?

返回 object 的字符串表示,并為遞歸數據結構提供保護。 如果 object 的表示形式公開了一個遞歸條目,該遞歸引用會被表示為 <Recursion on typename with id=number>。 該表示因而不會進行其它格式化。

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

PrettyPrinter 對象?

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 已格式化版本,指明結果是否可讀的旗標,以及指明是否檢測到遞歸的旗標。 第一個參數是要表示的對象。 第二個是以對象 id() 為鍵的字典,這些對象是當前表示上下文的一部分(影響 object 表示的直接和間接容器);如果需要呈現一個已經在 context 中表示的對象,則第三個返回值應當為 True。 對 format() 方法的遞歸調用應當將容器的附加條目添加到此字典中。 第三個參數 maxlevels 給出了對遞歸的請求限制;如果沒有請求限制則其值將為 0。 此參數應當不加修改地傳給遞歸調用。 第四個參數 level 給出于當前層級;傳給遞歸調用的參數值應當小于當前調用的值。

示例?

為了演示 pprint() 函數及其形參的幾種用法,讓我們從 PyPI 獲取關于某個項目的信息:

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

pprint() 以其基本形式顯示了整個對象:

>>> pprint.pprint(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.pprint(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.pprint(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'}