python standard library pprint

python 标准库 pprint

今天凌晨,突闻噩耗, 「黑曼巴」 Kobe Bryant(科比) 永远离开了我们,永远的24号,最伟大的nba球员,没有之一,R.I.P。

源码

源代码: Lib/pprint.py

主要类和函数,节选自源码

1
2
__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
"PrettyPrinter", "pp"]

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

格式化后的形式会在可能的情况下以单行来表示对象,并在无法在允许宽度内容纳对象的情况下将其分为多行。 如果你需要调整宽度限制则应显式地构造 PrettyPrinter 对象。

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

pprint 模块定义了一个类:

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

    构造一个 PrettyPrinter 实例。 此构造器接受几个关键字形参。 使用 stream 关键字可设置输出流;流对象使用的唯一方法是文件协议的 write() 方法。 如果未指定此关键字,则 PrettyPrinter 会选择 sys.stdout。 每个递归层次的缩进量由 indent 指定;默认值为一。 其他值可导致输出看起来有些怪异,,但可使得嵌套结构更易区分。 可被打印的层级数量由 depth 控制;如果数据结构的层级被打印得过深,其所包含的下一层级会被替换为 ...。 在默认情况下,对被格式化对象的层级深度没有限制。 希望的输出宽度可使用 width 形参来限制;默认值为 80 个字符。 如果一个结构无法在限定宽度内被格式化,则将做到尽可能接近。 如果 compact 为假值(默认)则长序列的每一项将被格式化为单独的行。 如果 compact 为真值,则将在 width 可容纳的的情况下把尽可能多的项放入每个输出行。 如果 sort_dicts 为真值(默认),字典将被格式化为按键排序,否则将按插入顺序显示。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    >>> 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, sort_dicts=True*)

    object 的格式化表示作为字符串返回。 indent, width, depth, compactsort_dicts 将作为格式化形参被传入 PrettyPrinter 构造器。在 3.4 版更改: 增加了 compact 形参。在 3.8 版更改: 增加了 sort_dicts 形参。

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

    打印 object 的格式化表示并附带一个换行符。 如果 sort_dicts 为假值(默认),字典将按键的插入顺序显示,否则将按字典键排序。 argskwargs 将作为格式化形参被传给 pprint()3.8 新版功能.

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

    stream 上打打印 object 的格式化表示,并附带一个换行符。 如果 streamNone,则使用 sys.stdout。 这可以替代 print() 函数在交互式解释器中使用以查看值(你甚至可以执行重新赋值 print = pprint.pprint 以在特定作用域中使用)。 indent, width, depth, compactsort_dicts 将作为格式化形参被传给 PrettyPrinter 构造器。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> 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']

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 获取关于某个项目的信息:

1
2
3
4
5
>>> 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() 以其基本形式显示了整个对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
>>> 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 (更深层的内容将使用省略号):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
>>> 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。 如果一个对象无法被拆分,则将超出指定宽度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
>>> 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'}

小结

1. 常用格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import pprint
>>> data = [(1,{'a':'A','b':'B','c':'C','d':'D'}),(2,{'e':'E','f':'F','g':'G','h':'H','i':'I','j':'J','k':'K','l':'L'}),]
>>> pprint.pprint(data)
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'})]

2. 格式化序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> data = [(1,{'a':'A','b':'B','c':'C','d':'D'}),(2,{'e':'E','f':'F','g':'G','h':'H','i':'I','j':'J','k':'K','l':'L'}),]
>>> result=pprint.pformat(data)
>>> for key in result.splitlines():
print(key)


[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'})]

3. 复杂的格式化,用于调试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import pprint;
import re;

def pprintDemo():
varsList = [
[1, 2, 3],
["ab", "c", "def"],
re.compile("\w+"),
("123", "abc"),
{
"key1":"value1",
"key2":"value2",
},
];

for value in varsList:
print(value);

print("-"*80)

pp = pprint.PrettyPrinter(indent=4);
for value in varsList:
pp.pprint(value);

print("-"*80)
stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni'];
stuff.insert(0, stuff[:])
print stuff;
print("-"*80)
pp.pprint(stuff)

if __name__ == '__main__':
pprintDemo();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[1, 2, 3]
['ab', 'c', 'def']
<_sre.SRE_Pattern object at 0x00000000030DD378>
('123', 'abc')
{'key2': 'value2', 'key1': 'value1'}
--------------------------------------------------------------------------------
[1, 2, 3]
['ab', 'c', 'def']
<_sre.SRE_Pattern object at 0x00000000030DD378>
('123', 'abc')
{ 'key1': 'value1', 'key2': 'value2'}
================================================================================
[['spam', 'eggs', 'lumberjack', 'knights', 'ni'], 'spam', 'eggs', 'lumberjack', 'knights', 'ni']
--------------------------------------------------------------------------------
[ ['spam', 'eggs', 'lumberjack', 'knights', 'ni'],
'spam',
'eggs',
'lumberjack',
'knights',
'ni']
坚持原创技术分享,您的支持将鼓励我继续创作!