pprint — 데이터 예쁘게 인쇄
pprint — 데이터 예쁘게 인쇄
소스 코드: Lib/pprint.py
pprint 모듈은 임의의 Python 데이터 구조를 인터프리터에 대한 입력으로 사용할 수 있는 형식으로 "예쁘게 인쇄(pretty-print)"하는 기능을 제공해요. 형식화된 구조에 기본 Python 타입이 아닌 객체가 포함되면 그 표현은 로드 가능하지 않을 수 있어요. 파일, 소켓, 클래스 같은 객체와 Python 리터럴로 표현할 수 없는 다른 많은 객체가 포함되면 그럴 수 있어요.
형식화된 표현은 가능하면 객체를 단일 줄에 유지하고, 허용된 너비(기본 80문자로 width 매개변수로 조정 가능)에 맞지 않으면 여러 줄로 나눠요.
버전 3.9에서 변경: types.SimpleNamespace 예쁘게 인쇄 지원 추가.
버전 3.10에서 변경: dataclasses.dataclass 예쁘게 인쇄 지원 추가.
출처: Python 표준 라이브러리
본문
함수 (Functions)
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(Any) — 인쇄할 객체.stream(file-like object | None) — 그것의write()메서드를 호출해 출력이 쓰일 파일류 객체.None(기본)이면sys.stdout이 사용돼요.indent(int) — 각 중첩 수준에 추가되는 들여쓰기 양.width(int) — 출력에서 줄당 원하는 최대 문자 수. 구조를width제약 안에 형식화할 수 없으면 최선을 다해 형식화돼요.depth(int | None) — 인쇄될 수 있는 중첩 수준 수. 인쇄 중인 데이터 구조가 너무 깊으면 다음 포함 수준이...로 대체돼요.None(기본)이면 형식화되는 객체의 깊이에 제약이 없어요.compact(bool) — 긴 시퀀스를 형식화하는 방식을 제어.False(기본)면 시퀀스의 각 항목이 별도의 줄에 형식화되고, 그렇지 않으면 너비 내에 맞는 만큼의 항목이 각 출력 줄에 형식화돼요.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)
기본적으로 sort_dicts를 True로 설정한 pp()의 별칭이에요. 그러면 사전의 키가 자동으로 정렬돼요. False가 기본인 pp()를 대신 사용하고 싶을 수도 있어요.
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)
__repr__이 재정의되지 않은 dict, list, tuple의 인스턴스 또는 하위 클래스 같은 몇몇 공통 데이터 구조에서 재귀로부터 보호되는 object의 문자열 표현을 반환해요. object의 표현이 재귀 항목을 노출하면 재귀 참조가 <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를 반환한다는 점에 주의하세요. PrettyPrinter의 depth 매개변수가 설정되고 객체가 허용된 것보다 깊으면 False를 반환해요.
PrettyPrinter.isrecursive(object)
객체가 재귀 표현을 요구하는지 판단해요. 이 메서드는 하위 클래스가 객체가 문자열로 변환되는 방식을 수정할 수 있게 하는 훅으로 제공돼요. 기본 구현은 saferepr() 구현의 내부를 사용해요.
PrettyPrinter.format(object, context, maxlevels, level)
세 값을 반환해요: 문자열로서의 object의 형식화된 버전, 결과가 읽을 수 있는지 나타내는 플래그, 재귀가 감지되었는지 나타내는 플래그. 첫 인자는 제시할 객체예요. 두 번째는 현재 제시 맥락의 일부인(제시에 영향을 미치는 object의 직접·간접 컨테이너) 객체의 id()를 키로 담는 사전이에요. context에 이미 표현된 객체를 제시해야 하면 세 번째 반환 값은 True여야 해요. format() 메서드에 대한 재귀 호출은 컨테이너에 대한 추가 항목을 이 사전에 추가해야 해요. 세 번째 인자 maxlevels는 재귀에 대한 요청된 제한을 줘요. 요청된 제한이 없으면 0이에요. 이 인자는 재귀 호출에 수정 없이 전달해야 해요. 네 번째 인자 level은 현재 수준을 줘요. 재귀 호출에는 현재 호출의 수준보다 작은 값을 전달해야 해요.
예제 (Example)
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': '[email protected]',
'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': '[email protected]',
'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': '[email protected]',
'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'}
더 알아보기
repr— 대체 표현을 위한 정밀str()변환.- pprint (원문)