Документация Python неофициальный перевод
Содержание страницы

8.11. pprint – Форматирование данныхpprint – Data pretty printer

Исходный код: Lib/pprint.py


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

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

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

Модуль pprint определяет один класс:

class pprint.PrettyPrinter(indent=1, width=80, depth=None, stream=None)

Создаёт экземпляр PrettyPrinter. Этот конструктор понимает несколько именованных параметров. Выходной поток данных можно задать с помощью ключевого слова stream; единственный метод, используемый на объекте потока данных – это метод write() из протокола файлов. Если не указано, PrettyPrinter использует sys.stdout. Ещё три параметра могут управлять форматированным представлением. Ключевые слова: indent, depth и width. Величина отступа, добавляемого на каждый рекурсивный уровень, задаётся параметром indent; по умолчанию – один. Другие значения могут сделать вывод немного необычным, но помогают лучше различать вложенность. Количество уровней, которые могут быть выведены, контролируется параметром depth; если выводимая структура данных слишком глубока, следующий вложенный уровень заменяется на .... По умолчанию ограничений на глубину форматируемых объектов нет. Желаемая ширина вывода задаётся параметром width; по умолчанию 80 символов. Если структуру невозможно отформатировать в заданной ширине, будет предпринята наилучшая попытка.

>>> 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']
>>> 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 поддерживает несколько производных функций:

pprint.pformat(object, indent=1, width=80, depth=None)

Возвращает форматированное представление object в виде строки. Параметры indent, width и depth будут переданы конструктору PrettyPrinter в качестве параметров форматирования.

pprint.pprint(object, stream=None, indent=1, width=80, depth=None)

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

>>> 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 «читаемым» (readable) или может быть использовано для восстановления значения с помощью 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']"

8.11.1. Объекты PrettyPrinterPrettyPrinter Objects

Экземпляры PrettyPrinter имеют следующие методы:

PrettyPrinter.pformat(object)

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

PrettyPrinter.pprint(object)

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

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

PrettyPrinter.isreadable(object)

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

PrettyPrinter.isrecursive(object)

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

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

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

Возвращает три значения: отформатированную версию object в виде строки, флаг, указывающий, является ли результат читаемым, и флаг, указывающий, была ли обнаружена рекурсия. Первый аргумент – отображаемый объект. Второй – словарь, который содержит id() объектов, являющихся частью текущего контекста представления (прямые и косвенные контейнеры для object, влияющие на представление), в качестве ключей; если нужно представить объект, который уже присутствует в context, третье возвращаемое значение должно быть True. Рекурсивные вызовы метода format() должны добавлять дополнительные записи для контейнеров в этот словарь. Третий аргумент, maxlevels, задаёт запрошенное ограничение на рекурсию; если ограничения нет, он равен 0. Этот аргумент следует передавать в рекурсивные вызовы без изменений. Четвёртый аргумент, level, задаёт текущий уровень; рекурсивным вызовам следует передавать значение меньше текущего.

8.11.2. ПримерExample

Чтобы продемонстрировать несколько вариантов использования функции pprint() и её параметров, давайте получим информацию о проекте из PyPI:

>>> import json
>>> import pprint
>>> from urllib.request import urlopen
>>> with urlopen('http://pypi.python.org/pypi/configparser/json') as url:
...     http_info = url.info()
...     raw_data = url.read().decode(http_info.get_content_charset())
>>> project_info = json.loads(raw_data)
>>> result = {'headers': http_info.items(), 'body': project_info}

В базовом виде pprint() отображает весь объект:

>>> pprint.pprint(result)
{'body': {'info': {'_pypi_hidden': False,
                   '_pypi_ordering': 12,
                   'classifiers': ['Development Status :: 4 - Beta',
                                   'Intended Audience :: Developers',
                                   'License :: OSI Approved :: MIT License',
                                   'Natural Language :: English',
                                   'Operating System :: OS Independent',
                                   'Programming Language :: Python',
                                   'Programming Language :: Python :: 2',
                                   'Programming Language :: Python :: 2.6',
                                   'Programming Language :: Python :: 2.7',
                                   'Topic :: Software Development :: Libraries',
                                   'Topic :: Software Development :: Libraries :: Python Modules'],
                   'download_url': 'UNKNOWN',
                   'home_page': 'http://docs.python.org/py3k/library/configparser.html',
                   'keywords': 'configparser ini parsing conf cfg configuration file',
                   'license': 'MIT',
                   'name': 'configparser',
                   'package_url': 'http://pypi.python.org/pypi/configparser',
                   'platform': 'any',
                   'release_url': 'http://pypi.python.org/pypi/configparser/3.2.0r3',
                   'requires_python': None,
                   'stable_version': None,
                   'summary': 'This library brings the updated configparser from Python 3.2+ to Python 2.6-2.7.',
                   'version': '3.2.0r3'},
        'urls': [{'comment_text': '',
                  'downloads': 47,
                  'filename': 'configparser-3.2.0r3.tar.gz',
                  'has_sig': False,
                  'md5_digest': '8500fd87c61ac0de328fc996fce69b96',
                  'packagetype': 'sdist',
                  'python_version': 'source',
                  'size': 32281,
                  'upload_time': '2011-05-10T16:28:50',
                  'url': 'http://pypi.python.org/packages/source/c/configparser/configparser-3.2.0r3.tar.gz'}]},
'headers': [('Date', 'Sat, 14 May 2011 12:48:52 GMT'),
            ('Server', 'Apache/2.2.16 (Debian)'),
            ('Content-Disposition', 'inline'),
            ('Connection', 'close'),
            ('Transfer-Encoding', 'chunked'),
            ('Content-Type', 'application/json; charset="UTF-8"')]}

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

>>> pprint.pprint(result, depth=3)
{'body': {'info': {'_pypi_hidden': False,
                   '_pypi_ordering': 12,
                   'classifiers': [...],
                   'download_url': 'UNKNOWN',
                   'home_page': 'http://docs.python.org/py3k/library/configparser.html',
                   'keywords': 'configparser ini parsing conf cfg configuration file',
                   'license': 'MIT',
                   'name': 'configparser',
                   'package_url': 'http://pypi.python.org/pypi/configparser',
                   'platform': 'any',
                   'release_url': 'http://pypi.python.org/pypi/configparser/3.2.0r3',
                   'requires_python': None,
                   'stable_version': None,
                   'summary': 'This library brings the updated configparser from Python 3.2+ to Python 2.6-2.7.',
                   'version': '3.2.0r3'},
        'urls': [{...}]},
'headers': [('Date', 'Sat, 14 May 2011 12:48:52 GMT'),
            ('Server', 'Apache/2.2.16 (Debian)'),
            ('Content-Disposition', 'inline'),
            ('Connection', 'close'),
            ('Transfer-Encoding', 'chunked'),
            ('Content-Type', 'application/json; charset="UTF-8"')]}

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

>>> pprint.pprint(result['headers'], width=30)
[('Date',
  'Sat, 14 May 2011 12:48:52 GMT'),
 ('Server',
  'Apache/2.2.16 (Debian)'),
 ('Content-Disposition',
  'inline'),
 ('Connection', 'close'),
 ('Transfer-Encoding',
  'chunked'),
 ('Content-Type',
  'application/json; charset="UTF-8"')]