pprint --- 數(shù)據(jù)美化輸出?

源代碼: Lib/pprint.py


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

格式化后的形式會(huì)在可能的情況下以單行來表示對象,并在無法在允許寬度內(nèi)容納對象的情況下將其分為多行。 如果你需要調(diào)整寬度限制則應(yīng)顯式地構(gòu)造 PrettyPrinter 對象。

字典在計(jì)算其顯示形式前會(huì)先根據(jù)鍵來排序。

在 3.9 版更改: 添加了對美化打印 types.SimpleNamespace 的支持。

在 3.10 版更改: 添加了對美化打印 dataclasses.dataclass 的支持。

pprint 模塊定義了一個(gè)類:

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

構(gòu)造一個(gè) PrettyPrinter 實(shí)例。 這個(gè)構(gòu)造器支持一些關(guān)鍵字形參。

stream (default sys.stdout) is a file-like object to which the output will be written by calling its write() method. If both stream and sys.stdout are None, then pprint() silently returns.

其他值可用來配置復(fù)雜數(shù)據(jù)結(jié)構(gòu)嵌套要以何種形式被展示。

indent (默認(rèn)為 1) 指定要為每個(gè)縮進(jìn)層級添加的縮進(jìn)量。

depth 控制可被打印的縮進(jìn)層級數(shù)量;如果要打印的數(shù)據(jù)結(jié)構(gòu)層級過深,則其所包含的下一層級將用 ... 替換。 默認(rèn)情況下,對于被格式化對象的層級深度沒有任何限制。

width (默認(rèn)為 80) 指定輸出中每行所允許的最大字符數(shù)。 如果一個(gè)數(shù)據(jù)結(jié)構(gòu)無法在寬度限制之內(nèi)被格式化,將顯示盡可能多的內(nèi)容。

compact 影響長序列(列表、元組、集合等等)的格式化方式。 如果 compact 為假值(默認(rèn))則序列的每一項(xiàng)將格式化為單獨(dú)的行。 如果 compact 為真值,則每個(gè)輸出行格式化時(shí)將在 width 的限制之內(nèi)盡可能地容納多個(gè)條目。

如果 sort_dicts 為真值(默認(rèn)),字典在格式化時(shí)將基于鍵進(jìn)行排序,否則它們將按插入順序顯示。

如果 underscore_numbers 為真值,整數(shù)在格式化時(shí)將使用 _ 字符作為千位分隔符,否則不顯示下劃線(默認(rèn))。

在 3.4 版更改: 增加了 compact 形參。

在 3.8 版更改: 增加了 sort_dicts 形參。

在 3.10 版更改: 添加了 underscore_numbers 形參。

在 3.11 版更改: No longer attempts to write to sys.stdout if it is None.

>>>
>>> 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.pformat(object, indent=1, width=80, depth=None, *, compact=False, sort_dicts=True, underscore_numbers=False)?

Return the formatted representation of object as a string. indent, width, depth, compact, sort_dicts and underscore_numbers are passed to the PrettyPrinter constructor as formatting parameters and their meanings are as described in its documentation above.

pprint.pp(object, *args, sort_dicts=False, **kwargs)?

打印 object 的格式化表示并附帶一個(gè)換行符。 如果 sort_dicts 為假值(默認(rèn)),字典將按鍵的插入順序顯示,否則將按字典鍵排序。 argskwargs 將作為格式化形參被傳給 pprint()

3.8 新版功能.

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

Prints the formatted representation of object on stream, followed by a newline. If stream is None, sys.stdout is used. This may be used in the interactive interpreter instead of the print() function for inspecting values (you can even reassign print = pprint.pprint for use within a scope).

The configuration parameters stream, indent, width, depth, compact, sort_dicts and underscore_numbers are passed to the PrettyPrinter constructor and their meanings are as described in its documentation above.

>>>
>>> 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() 重新構(gòu)建對象的值。 此函數(shù)對于遞歸對象總是返回 False

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

Determine if object requires a recursive representation. This function is subject to the same limitations as noted in saferepr() below and may raise an RecursionError if it fails to detect a recursive object.

此外還定義了一個(gè)支持函數(shù):

pprint.saferepr(object)?

Return a string representation of object, protected against recursion in some common data structures, namely instances of dict, list and tuple or subclasses whose __repr__ has not been overridden. If the representation of object exposes a recursive entry, the recursive reference will be represented as <Recursion on typename with id=number>. The representation is not otherwise formatted.

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

PrettyPrinter 對象?

PrettyPrinter 的實(shí)例具有下列方法:

PrettyPrinter.pformat(object)?

返回 object 格式化表示。 這會(huì)將傳給 PrettyPrinter 構(gòu)造器的選項(xiàng)納入考慮。

PrettyPrinter.pprint(object)?

在所配置的流上打印 object 的格式化表示,并附加一個(gè)換行符。

下列方法提供了與同名函數(shù)相對應(yīng)的實(shí)現(xiàn)。 在實(shí)例上使用這些方法效率會(huì)更高一些,因?yàn)椴恍枰獎(jiǎng)?chuàng)建新的 PrettyPrinter 對象。

PrettyPrinter.isreadable(object)?

確定對象的格式化表示是否“可讀”,或者是否可使用 eval() 重建對象值。 請注意此方法對于遞歸對象將返回 False。 如果設(shè)置了 PrettyPrinterdepth 形參并且對象深度超出允許范圍,此方法將返回 False。

PrettyPrinter.isrecursive(object)?

確定對象是否需要遞歸表示。

此方法作為一個(gè)鉤子提供,允許子類修改將對象轉(zhuǎn)換為字符串的方式。 默認(rèn)實(shí)現(xiàn)使用 saferepr() 實(shí)現(xiàn)的內(nèi)部方式。

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

返回三個(gè)值:字符串形式的 object 已格式化版本,指明結(jié)果是否可讀的旗標(biāo),以及指明是否檢測到遞歸的旗標(biāo)。 第一個(gè)參數(shù)是要表示的對象。 第二個(gè)是以對象 id() 為鍵的字典,這些對象是當(dāng)前表示上下文的一部分(影響 object 表示的直接和間接容器);如果需要呈現(xiàn)一個(gè)已經(jīng)在 context 中表示的對象,則第三個(gè)返回值應(yīng)當(dāng)為 True。 對 format() 方法的遞歸調(diào)用應(yīng)當(dāng)將容器的附加條目添加到此字典中。 第三個(gè)參數(shù) maxlevels 給出了對遞歸的請求限制;如果沒有請求限制則其值將為 0。 此參數(shù)應(yīng)當(dāng)不加修改地傳給遞歸調(diào)用。 第四個(gè)參數(shù) level 給出于當(dāng)前層級;傳給遞歸調(diào)用的參數(shù)值應(yīng)當(dāng)小于當(dāng)前調(diào)用的值。

示例?

為了演示 pprint() 函數(shù)及其形參的幾種用法,讓我們從 PyPI 獲取關(guān)于某個(gè)項(xiàng)目的信息:

>>>
>>> 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() 以其基本形式顯示了整個(gè)對象:

>>>
>>> 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'}

結(jié)果可以被限制到特定的 depth (更深層的內(nèi)容將使用省略號):

>>>
>>> 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'}

此外,還可以設(shè)置建議的最大字符 width。 如果一個(gè)對象無法被拆分,則將超出指定寬度:

>>>
>>> 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'}