pprint — Данные красивого принтера

Источник: Lib/pprint.py


Модуль pprint обеспечивает возможность «красивой печати» произвольных структур данных Python в форме, которую можно использовать в качестве входных данных для интерпретатора. Если отформатированные структуры включают объекты, которые не являются фундаментальными типами Python, представление может быть не загружаемым. Это может произойти, если в структуру включены такие объекты, как файлы, сокеты или классы, а также многие другие объекты, которые не могут быть представлены в виде литералов Python.

Форматированное представление сохраняет объекты в одной строке, если это возможно, и разбивает их на несколько строк, если они не помещаются в допустимую ширину, регулируемую параметром width, по умолчанию равным 80 символам.

Перед выводом на экран словари сортируются по ключам.

Изменено в версии 3.9: Добавлена поддержка красивой печати types.SimpleNamespace.

Изменено в версии 3.10: Добавлена поддержка красивой печати dataclasses.dataclass.

Функции

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

Выводит форматированное представление object, за которым следует новая строка. Если sort_dicts равно false (по умолчанию), словари будут отображаться с ключами в порядке вставки, в противном случае ключи диктов будут отсортированы. args и kwargs будут переданы в pprint() в качестве параметров форматирования.

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

Added in version 3.8.

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

Выводит форматированное представление объекта в поток, после чего следует новая строка. Если stream имеет значение None, то используется sys.stdout. Эта функция может использоваться в интерактивном интерпретаторе вместо функции print() для проверки значений (вы даже можете переназначить print = pprint.pprint для использования внутри области видимости).

Параметры конфигурации stream, indent, width, depth, compact, sort_dicts и underscore_numbers передаются конструктору PrettyPrinter, и их значения описаны в документации ниже.

Обратите внимание, что sort_dicts по умолчанию имеет значение True, и вы можете захотеть использовать вместо него значение pp(), где по умолчанию стоит значение False.

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

Возвращает форматированное представление объекта в виде строки. indent, width, depth, compact, sort_dicts и underscore_numbers передаются конструктору PrettyPrinter в качестве параметров форматирования, и их значения описаны в документации ниже.

pprint.isreadable(object)

Определите, является ли форматированное представление объекта «читаемым» или может быть использовано для восстановления значения с помощью eval(). Для рекурсивных объектов всегда возвращается False.

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

Определите, требует ли объект рекурсивного представления. На эту функцию распространяются те же ограничения, что и на saferepr() ниже, и она может выдать ошибку RecursionError, если не обнаружит рекурсивный объект.

pprint.saferepr(object)

Возвращает строковое представление объекта, защищенное от рекурсии в некоторых распространенных структурах данных, а именно в экземплярах dict, list и tuple или подклассах, чей __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. Этот конструктор понимает несколько параметров ключевых слов.

stream (по умолчанию sys.stdout) - это file-like object, в который будет записан вывод путем вызова его метода write(). Если и stream, и sys.stdout являются None, то pprint() возвращается беззвучно.

Другие значения настраивают способ отображения вложенности сложных структур данных.

indent (по умолчанию 1) задает количество отступов, добавляемых для каждого уровня вложенности.

depth управляет количеством уровней вложенности, которые могут быть выведены на печать; если выводимая структура данных слишком глубока, следующий содержащийся в ней уровень заменяется на .... По умолчанию глубина форматируемых объектов не ограничена.

width (по умолчанию 80) задает желаемое максимальное количество символов в строке вывода. Если структура не может быть отформатирована в рамках ограничения ширины, будет предпринята попытка.

compact влияет на способ форматирования длинных последовательностей (списков, кортежей, множеств и т. д.). Если значение compact равно false (по умолчанию), то каждый элемент последовательности будет отформатирован в отдельной строке. Если compact равно true, то в каждой строке будет отформатировано столько элементов, сколько поместится в width.

Если значение sort_dicts равно true (по умолчанию), словари будут отформатированы с сортировкой ключей, в противном случае они будут отображаться в порядке вставки.

Если значение underscore_numbers равно true, целые числа будут отформатированы с символом _ для разделителя тысяч, в противном случае символы подчеркивания не будут отображаться (по умолчанию).

Изменено в версии 3.4: Добавлен параметр компактность.

Изменено в версии 3.8: Добавлен параметр sort_dicts.

Изменено в версии 3.10: Добавлен параметр underscore_numbers.

Изменено в версии 3.11: Больше не пытается записывать в sys.stdout, если он равен 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', (...)))))))

У экземпляров PrettyPrinter есть следующие методы:

PrettyPrinter.pformat(object)

Возвращает форматированное представление объекта. При этом учитываются параметры, переданные в конструктор PrettyPrinter.

PrettyPrinter.pprint(object)

Печать форматированного представления объекта в сконфигурированный поток, после чего следует новая строка.

Следующие методы представляют собой реализации одноименных функций. Использование этих методов на экземпляре несколько эффективнее, поскольку не нужно создавать новые объекты PrettyPrinter.

PrettyPrinter.isreadable(object)

Определите, является ли форматированное представление объекта «читаемым» или может быть использовано для восстановления значения с помощью eval(). Обратите внимание, что для рекурсивных объектов возвращается False. Если параметр depth в PrettyPrinter установлен и объект находится глубже, чем разрешено, возвращается False.

PrettyPrinter.isrecursive(object)

Определите, требует ли объект рекурсивного представления.

Этот метод предоставляется в качестве крючка, позволяющего подклассам изменять способ преобразования объектов в строки. Реализация по умолчанию использует внутренности реализации saferepr().

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

Возвращает три значения: отформатированную версию объекта в виде строки, флаг, указывающий, доступен ли результат для чтения, и флаг, указывающий, была ли обнаружена рекурсия. Первый аргумент - объект, который должен быть представлен. Второй - словарь, содержащий в качестве ключей 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/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'}

Результат может быть ограничен определенной глубиной (многоточие используется для более глубокого содержимого):

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

Кроме того, может быть предложена максимальная ширина символов. Если длинный объект не может быть разделен, указанная ширина будет превышена:

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