pprint --- چاپگر زیبای داده‌ها

کد منبع: Lib/pprint.py


ماژول pprint قابلیت «زیبانویسی» (pretty-print) ساختارهای داده‌ای دلخواه پایتون را به شکلی فراهم می‌کند که بتوان از آن به‌عنوان ورودی برای مفسر استفاده کرد. اگر ساختارهای قالب‌بندی‌شده شامل اشیایی باشند که از انواع بنیادی پایتون نیستند، ممکن است نمایش آن‌ها قابل بارگذاری نباشد. این حالت ممکن است زمانی پیش بیاید که اشیایی مانند پرونده‌ها، سوکت‌ها یا کلاس‌ها، و همچنین بسیاری از اشیاء دیگر که نمی‌توان آن‌ها را به‌صورت مقادیر لفظی پایتون نمایش داد، گنجانده شده باشند.

بازنمایی قالب‌بندی‌شده شیء‌ها را در صورت امکان روی یک خط نگه می‌دارد و اگر در عرض مجاز جا نشوند، آن‌ها را در چند خط می‌شکند؛ عرض مجاز با پارامتر width قابل تنظیم است و مقدار پیش‌فرض این پارامتر ۸۰ نویسه است.

تغییر یافته در نسخه‌ی 3.9: پشتیبانی از زیبانویسی types.SimpleNamespace افزوده شد.

تغییر یافته در نسخه‌ی 3.10: پشتیبانی از زیبانویسی (pretty-printing) برای dataclasses.dataclass افزوده شد.

توابع

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

بازنمایی قالب‌بندی‌شده‌ی object را چاپ می‌کند و سپس یک خط جدید درج می‌کند. می‌توان از این تابع در مفسر تعاملی به جای تابع print() برای بررسی مقادیر استفاده کرد. نکته: می‌توانید با انتساب دوباره‌ی print = pprint.pp، از آن در یک محدوده استفاده کنید.

پارامترها:
  • object -- شیء‌ای که باید چاپ شود.

  • stream (file-like object | None) -- یک شیء شبه‌پرونده که خروجی با فراخوانی متد write() آن نوشته می‌شود. اگر None (پیش‌فرض) باشد، از sys.stdout استفاده می‌شود.

  • indent (int) -- مقدار تورفتگی افزوده‌شده برای هر سطح تودرتو.

  • width (int) -- حداکثر تعداد مطلوب نویسه‌ها در هر خط از خروجی. اگر ساختاری نتواند در محدودیت عرض قالب‌بندی شود، بهترین تلاش ممکن انجام خواهد شد.

  • depth (int | None) -- تعداد سطوح تودرتویی که ممکن است چاپ شوند. اگر ساختار داده‌ای که چاپ می‌شود بیش از حد عمیق باشد، سطح داخلی بعدی با ... جایگزین می‌شود. اگر None (پیش‌فرض) باشد، هیچ محدودیتی بر عمق اشیاء قالب‌بندی‌شده وجود ندارد.

  • compact (bool) -- نحوه قالب‌بندی دنباله‌های طولانی را کنترل کنید. اگر False (پیش‌فرض) باشد، هر آیتم از یک دنباله در یک خط جداگانه قالب‌بندی می‌شود، در غیر این صورت، در هر خط خروجی، هر تعداد آیتم که در width جا شوند قالب‌بندی می‌شوند.

  • sort_dicts (bool) -- اگر True باشد، دیکشنری‌ها با کلیدهای مرتب‌شده قالب‌بندی می‌شوند، در غیر این صورت به ترتیب درج نمایش داده می‌شوند (پیش‌فرض).

  • underscore_numbers (bool) -- اگر True باشد، اعداد صحیح با نویسه _ به‌عنوان جداکننده هزارگان قالب‌بندی می‌شوند، در غیر این صورت زیرسطرها نمایش داده نمی‌شوند (حالت پیش‌فرض).

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

اضافه شده در نسخه‌ی 3.8.

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

نام مستعاری برای pp() که sort_dicts به‌طور پیش‌فرض روی True تنظیم شده است و کلیدهای دیکشنری‌ها را به‌صورت خودکار مرتب می‌کند؛ ممکن است بخواهید به‌جای آن از pp() استفاده کنید که در آن این گزینه به‌طور پیش‌فرض False است.

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

بازنمایی قالب‌بندی‌شده‌ی object را به‌صورت یک رشته برمی‌گرداند. indent، width، depth، compact، sort_dicts و underscore_numbers به‌عنوان پارامترهای قالب‌بندی به سازنده‌ی PrettyPrinter داده می‌شوند و معنای آن‌ها همان‌گونه است که در مستندات بالا توضیح داده شده است.

pprint.isreadable(object)

تعیین می‌کند که آیا نمایش قالب‌بندی‌شده‌ی object «خوانا» است، یا می‌توان از آن برای بازسازی مقدار با استفاده از eval() استفاده کرد. این همیشه برای اشیاء بازگشتی False را برمی‌گرداند.

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

تعیین می‌کند که آیا object به یک بازنمایی بازگشتی نیاز دارد یا خیر. این تابع مشمول همان محدودیت‌هایی است که در saferepr() در زیر به آن‌ها اشاره شده است و ممکن است در صورتی که نتواند یک شیء بازگشتی را تشخیص دهد، یک RecursionError پرتاب کند.

pprint.saferepr(object)

نمایش رشته‌ای از 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 ایجاد کنید.

آرگومان‌ها همان معنای مورد استفاده برای pp() را دارند. توجه داشته باشید که ترتیب آن‌ها متفاوت است، و مقدار پیش‌فرض sort_dicts برابر True است.

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

تغییر یافته در نسخه‌ی 3.4: پارامتر compact افزوده شد.

تغییر یافته در نسخه‌ی 3.8: پارامتر sort_dicts افزوده شد.

تغییر یافته در نسخه‌ی 3.10: پارامتر underscore_numbers اضافه شد.

تغییر یافته در نسخه‌ی 3.11: دیگر در صورتی که sys.stdout مقدار None باشد، تلاش نمی‌کند در آن بنویسد.

نمونه‌های PrettyPrinter متدهای زیر را دارند:

PrettyPrinter.pformat(object)

بازنمایی قالب‌بندی‌شده‌ی object را برمی‌گرداند. این گزینه‌های داده‌شده به سازنده‌ی PrettyPrinter را در نظر می‌گیرد.

PrettyPrinter.pprint(object)

نمایش قالب‌بندی‌شده‌ی object را روی جریان پیکربندی‌شده چاپ می‌کند و پس از آن یک خط جدید درج می‌کند.

متدهای زیر پیاده‌سازی‌های توابع متناظر با همین نام‌ها را ارائه می‌دهند. استفاده از این متدها بر روی یک نمونه کمی کارآمدتر است، زیرا نیازی به ایجاد اشیای جدید PrettyPrinter نیست.

PrettyPrinter.isreadable(object)

تعیین کنید که آیا بازنمایی قالب‌بندی‌شده شیء «خوانا» است یا می‌توان از آن برای بازسازی مقدار با استفاده از eval() استفاده کرد. توجه داشته باشید که این برای اشیاء بازگشتی False برمی‌گرداند. اگر پارامتر depth از PrettyPrinter تنظیم شده باشد و شیء عمیق‌تر از حد مجاز باشد، این False برمی‌گرداند.

PrettyPrinter.isrecursive(object)

تعیین می‌کند که آیا شیء به بازنمایی بازگشتی نیاز دارد یا خیر.

این متد به‌عنوان یک قلاب ارائه شده است تا زیرکلاس‌ها بتوانند نحوه تبدیل اشیاء به رشته را تغییر دهند. پیاده‌سازی پیش‌فرض از بخش‌های داخلی پیاده‌سازی saferepr() استفاده می‌کند.

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

سه مقدار را برمی‌گرداند: نسخه قالب‌بندی‌شده از object به‌صورت یک رشته، پرچمی که نشان می‌دهد آیا نتیجه خوانا است، و پرچمی که نشان می‌دهد آیا بازگشت تشخیص داده شده است. نخستین آرگومان، شیءای است که باید ارائه شود. دومین آرگومان، دیکشنری است که id() اشیایی را که بخشی از زمینه ارائه فعلی هستند (ظروف مستقیم و غیرمستقیم برای object که بر ارائه تأثیر می‌گذارند) به‌عنوان کلیدها شامل می‌شود؛ اگر شیءای که باید ارائه شود از قبل در context وجود داشته باشد، سومین مقدار بازگشتی باید True باشد. فراخوانی‌های بازگشتی متد format() باید ورودی‌های اضافی برای ظروف را به این دیکشنری اضافه کنند. سومین آرگومان، maxlevels، محدودیت درخواست‌شده برای بازگشت را مشخص می‌کند؛ اگر محدودیتی درخواست نشده باشد، این مقدار 0 خواهد بود. این آرگومان باید بدون تغییر به فراخوانی‌های بازگشتی ارسال شود. چهارمین آرگومان، level، سطح فعلی را مشخص می‌کند؛ فراخوانی‌های بازگشتی باید مقداری کمتر از مقدار فراخوانی فعلی دریافت کنند.

مثال

برای نمایش چندین کاربرد تابع pp() و پارامترهای آن، بیایید اطلاعاتی درباره‌ی یک پروژه را از PyPI واکشی کنیم:

>>> import json
>>> import pprint
>>> from urllib.request import urlopen
>>> with urlopen('https://pypi.org/pypi/sampleproject/1.2.0/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'}