在 Python 中使用漂亮的列印來美化您的資料結構
Python 中通常使用print函數來輸出結果,但是當資料結構複雜時,輸出内容就不夠美觀了,但是标準庫中的pprint是一個好工具。
- 了解為什麼需要pprint
- 了解如何使用 pprint()、
了解對Python漂亮印刷的需求
>>>
>>> from urllib import request
>>> response = request.urlopen("https://jsonplaceholder.typicode.com/users")
>>> json_response = response.read()
>>> import json
>>> users = json.loads(json_response)
>>>
>>> print(users)
[{'id': 1, 'name': 'Leanne Graham', 'username': 'Bret', 'email': '[email protected]', 'address': {'street': 'Kulas Light', 'suite': 'Apt. 556', 'city': 'Gwenborough', 'zipcode': '92998-3874', 'geo': {'lat': '-37.3159', 'lng': '81.1496'}}, 'phone': '1-770-736-8031 x56442', 'website': 'hildegard.org', 'company': {'name': 'Romaguera-Crona', 'catchPhrase': 'Multi-layered client-server neural-net', 'bs': 'harness real-time e-markets'}}, {'id': 2, 'name': 'Ervin Howell', 'username': 'Antonette', 'email': '[email protected]', 'address': {'street': 'Victor Plains', 'suite': 'Suite 879', 'city': 'Wisokyburgh', 'zipcode': '90566-7771', 'geo': {'lat': '-43.9509', 'lng': '-34.4618'}}, 'phone': '010-692-6593 x09125', 'website': 'anastasia.net', 'company': {'name': 'Deckow-Crist', 'catchPhrase': 'Proactive didactic contingency', 'bs': 'synergize scalable supply-chains'}}, {'id': 3, 'name': 'Clementine Bauch', 'username': 'Samantha', 'email': '[email protected]', 'address': {'street': 'Douglas Extension', 'suite': 'Suite 847', 'city': 'McKenziehaven', 'zipcode': '59590-4157', 'geo': {'lat': '-68.6102', 'lng': '-47.0653'}}, 'phone': '1-463-123-4447', 'website': 'ramiro.info', 'company': {'name': 'Romaguera-Jacobson', 'catchPhrase': 'Face to face bifurcated interface', 'bs': 'e-enable strategic applications'}}, {'id': 4, 'name': 'Patricia Lebsack', 'username': 'Karianne', 'email': '[email protected]', 'address': {'street': 'Hoeger Mall', 'suite': 'Apt. 692', 'city': 'South Elvis', 'zipcode': '53919-4257', 'geo': {'lat': '29.4572', 'lng': '-164.2990'}}, 'phone': '493-170-9623 x156', 'website': 'kale.biz', 'company': {'name': 'Robel-Corkery', 'catchPhrase': 'Multi-tiered zero tolerance productivity', 'bs': 'transition cutting-edge web services'}}, {'id': 5, 'name': 'Chelsey Dietrich', 'username': 'Kamren', 'email': '[email protected]', 'address': {'street': 'Skiles Walks', 'suite': 'Suite 351', 'city': 'Roscoeview', 'zipcode': '33263', 'geo': {'lat': '-31.8129', 'lng': '62.5342'}}, 'phone': '(254)954-1289', 'website': 'demarco.info', 'company': {'name': 'Keebler LLC', 'catchPhrase': 'User-centric fault-tolerant solution', 'bs': 'revolutionize end-to-end systems'}}, {'id': 6, 'name': 'Mrs. Dennis Schulist', 'username': 'Leopoldo_Corkery', 'email': '[email protected]', 'address': {'street': 'Norberto Crossing', 'suite': 'Apt. 950', 'city': 'South Christy', 'zipcode': '23505-1337', 'geo': {'lat': '-71.4197', 'lng': '71.7478'}}, 'phone': '1-477-935-8478 x6430', 'website': 'ola.org', 'company': {'name': 'Considine-Lockman', 'catchPhrase': 'Synchronised bottom-line interface', 'bs': 'e-enable innovative applications'}}, {'id': 7, 'name': 'Kurtis Weissnat', 'username': 'Elwyn.Skiles', 'email': '[email protected]', 'address': {'street': 'Rex Trail', 'suite': 'Suite 280', 'city': 'Howemouth', 'zipcode': '58804-1099', 'geo': {'lat': '24.8918', 'lng': '21.8984'}}, 'phone': '210.067.6132', 'website': 'elvis.io', 'company': {'name': 'Johns Group', 'catchPhrase': 'Configurable multimedia task-force', 'bs': 'generate enterprise e-tailers'}}, {'id': 8, 'name': 'Nicholas Runolfsdottir V', 'username': 'Maxime_Nienow', 'email': '[email protected]', 'address': {'street': 'Ellsworth Summit', 'suite': 'Suite 729', 'city': 'Aliyaview', 'zipcode': '45169', 'geo': {'lat': '-14.3990', 'lng': '-120.7677'}}, 'phone': '586.493.6943 x140', 'website': 'jacynthe.com', 'company': {'name': 'Abernathy Group', 'catchPhrase': 'Implemented secondary concept', 'bs': 'e-enable extensible e-tailers'}}, {'id': 9, 'name': 'Glenna Reichert', 'username': 'Delphine', 'email': '[email protected]', 'address': {'street': 'Dayna Park', 'suite': 'Suite 449', 'city': 'Bartholomebury', 'zipcode': '76495-3109', 'geo': {'lat': '24.6463', 'lng': '-168.8889'}}, 'phone': '(775)976-6794 x41206', 'website': 'conrad.com', 'company': {'name': 'Yost and Sons', 'catchPhrase': 'Switchable contextually-based project', 'bs': 'aggregate real-time technologies'}}, {'id': 10, 'name': 'Clementina DuBuque', 'username': 'Moriah.Stanton', 'email': '[email protected]', 'address': {'street': 'Kattie Turnpike', 'suite': 'Suite 198', 'city': 'Lebsackbury', 'zipcode': '31428-2261', 'geo': {'lat': '-38.2386', 'lng': '57.2232'}}, 'phone': '024-648-3804', 'website': 'ambrose.net', 'company': {'name': 'Hoeger LLC', 'catchPhrase': 'Centralized empowering task-force', 'bs': 'target end-to-end models'}}]
如果要輸出的内容非常長,那麼 你不得不将滾動條一直向右邊拖動。
for user in users:
print(user)
使用pprint
pprint是一個 Python 子產品,用于以漂亮的方式列印資料結構。 它長期以來一直是Python标準庫的一部分, 是以可以直接使用它。
>>>
>>> from pprint import pprint
>>>
>>> pprint(users)
>>>
>>> pprint(users)
[{'address': {'city': 'Gwenborough',
'geo': {'lat': '-37.3159', 'lng': '81.1496'},
'street': 'Kulas Light',
'suite': 'Apt. 556',
'zipcode': '92998-3874'},
'company': {'bs': 'harness real-time e-markets',
'catchPhrase': 'Multi-layered client-server neural-net',
'name': 'Romaguera-Crona'},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'},
{'address': {'city': 'Wisokyburgh',
'geo': {'lat': '-43.9509', 'lng': '-34.4618'},
'street': 'Victor Plains',
'suite': 'Suite 879',
'zipcode': '90566-7771'},
'company': {'bs': 'synergize scalable supply-chains',
'catchPhrase': 'Proactive didactic contingency',
'name': 'Deckow-Crist'},
'email': '[email protected]',
'id': 2,
'name': 'Ervin Howell',
'phone': '010-692-6593 x09125',
'username': 'Antonette',
'website': 'anastasia.net'},
...
{'address': {'city': 'Lebsackbury',
'geo': {'lat': '-38.2386', 'lng': '57.2232'},
'street': 'Kattie Turnpike',
'suite': 'Suite 198',
'zipcode': '31428-2261'},
'company': {'bs': 'target end-to-end models',
'catchPhrase': 'Centralized empowering task-force',
'name': 'Hoeger LLC'},
'email': '[email protected]',
'id': 10,
'name': 'Clementina DuBuque',
'phone': '024-648-3804',
'username': 'Moriah.Stanton',
'website': 'ambrose.net'}]
>>>
>>> from pprint import pp
>>> pp(users)
pp()隻是一個包裝, 它的行為方式完全相同。pprint()
depth 實際上可以控制顯示結果的深度或者說層級。
>>>
>>> pprint(users, depth=1)
[{...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}]
可以立即看到這确實是一個字典清單。 要進一步探索資料結構,您可以将深度增加一個級别, 這将在以下位置列印字典的所有頂級鍵:users
>>>
>>> pprint(users, depth=2)
[{'address': {...},
'company': {...},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'},
{'address': {...},
'company': {...},
'email': '[email protected]',
'id': 2,
'name': 'Ervin Howell',
'phone': '010-692-6593 x09125',
'username': 'Antonette',
'website': 'anastasia.net'},
...
{'address': {...},
'company': {...},
'email': '[email protected]',
'id': 10,
'name': 'Clementina DuBuque',
'phone': '024-648-3804',
'username': 'Moriah.Stanton',
'website': 'ambrose.net'}]
indent 資料縮進
列印表示的每個級别的縮程序度
>>>
>>> pprint(users[0], depth=1)
{'address': {...},
'company': {...},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
>>> pprint(users[0], depth=1, indent=4)
{ 'address': {...},
'company': {...},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
>>>
>>> pprint(users[0], depth=2, indent=4)
{ 'address': { 'city': 'Gwenborough',
'geo': {...},
'street': 'Kulas Light',
'suite': 'Apt. 556',
'zipcode': '92998-3874'},
'company': { 'bs': 'harness real-time e-markets',
'catchPhrase': 'Multi-layered client-server neural-net',
'name': 'Romaguera-Crona'},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
限制寬度:width
>>>
>>> pprint(users[0])
{'address': {'city': 'Gwenborough',
'geo': {'lat': '-37.3159', 'lng': '81.1496'},
'street': 'Kulas Light',
'suite': 'Apt. 556',
'zipcode': '92998-3874'},
'company': {'bs': 'harness real-time e-markets',
'catchPhrase': 'Multi-layered client-server neural-net',
'name': 'Romaguera-Crona'},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
寬度保留為預設值 80 個字元時
然而 字典将超過預設寬度, 是以把每個鍵放在一個新的行上。 字典、清單、元組和集合也是如此:users[0]['company']pprint()
>>>
>>> pprint(users[0], width=160)
{'address': {'city': 'Gwenborough', 'geo': {'lat': '-37.3159', 'lng': '81.1496'}, 'street': 'Kulas Light', 'suite': 'Apt. 556', 'zipcode': '92998-3874'},
'company': {'bs': 'harness real-time e-markets', 'catchPhrase': 'Multi-layered client-server neural-net', 'name': 'Romaguera-Crona'},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
如果将寬度設定為較大的值所有嵌套詞典都适合一行。
>>>
>>> pprint(users[0], width=500)
{'address': {'city': 'Gwenborough', 'geo': {'lat': '-37.3159', 'lng': '81.1496'}, 'street': 'Kulas Light', 'suite': 'Apt. 556', 'zipcode': '92998-3874'}, 'company': {'bs': 'harness real-time e-markets', 'catchPhrase': 'Multi-layered client-server neural-net', 'name': 'Romaguera-Crona'}, 'email': '[email protected]', 'id': 1, 'name': 'Leanne Graham', 'phone': '1-770-736-8031 x56442', 'username': 'Bret', 'website': 'hildegard.org'}
>>>
>>> pprint(users[0], width=5)
{'address': {'city': 'Gwenborough',
'geo': {'lat': '-37.3159',
'lng': '81.1496'},
'street': 'Kulas '
'Light',
'suite': 'Apt. '
'556',
'zipcode': '92998-3874'},
'company': {'bs': 'harness '
'real-time '
'e-markets',
'catchPhrase': 'Multi-layered '
'client-server '
'neural-net',
'name': 'Romaguera-Crona'},
'email': '[email protected]',
'id': 1,
'name': 'Leanne '
'Graham',
'phone': '1-770-736-8031 '
'x56442',
'username': 'Bret',
'website': 'hildegard.org'}
壓縮列:compact
>>>
>>> pprint(users, depth=1)
[{...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}]
>>> pprint(users, depth=1, width=40)
[{...},
{...},
{...},
{...},
{...},
{...},
{...},
{...},
{...},
{...}]
>>> pprint(users, depth=1, width=40, compact=True)
[{...}, {...}, {...}, {...}, {...},
{...}, {...}, {...}, {...}, {...}]
stream
其實就是可以把美化後的輸出,寫入其他地方,如檔案中
>>>
>>> with open("output.txt", mode="w") as file_object:
... pprint(users, stream=file_object)
字典排序:sort_dicts
>>>
>>> pprint(users[0], depth=1)
{'address': {...},
'company': {...},
'email': '[email protected]',
'id': 1,
'name': 'Leanne Graham',
'phone': '1-770-736-8031 x56442',
'username': 'Bret',
'website': 'hildegard.org'}
>>> pprint(users[0], depth=1, sort_dicts=False)
{'id': 1,
'name': 'Leanne Graham',
'username': 'Bret',
'email': '[email protected]',
'address': {...},
'phone': '1-770-736-8031 x56442',
'website': 'hildegard.org',
'company': {...}}
)
美化數字underscore_numbers
該參數是 Python 3.10 中引入的一項功能,它使長數字更具可讀性。 考慮到您到目前為止使用的示例不包含任何長數字 underscore_numbers
>>>
>>> number_list = [123456789, 10000000000000]
>>> pprint(number_list, underscore_numbers=True)
[123_456_789, 10_000_000_000_000]
建立自定義對象PrettyPrinter
>>>
>>> from pprint import PrettyPrinter
>>> custom_printer = PrettyPrinter(
... indent=4,
... width=100,
... depth=2,
... compact=True,
... sort_dicts=False,
... underscore_numbers=True
... )
...
>>> custom_printer.pprint(users[0])
{ 'id': 1,
'name': 'Leanne Graham',
'username': 'Bret',
'email': '[email protected]',
'address': { 'street': 'Kulas Light',
'suite': 'Apt. 556',
'city': 'Gwenborough',
'zipcode': '92998-3874',
'geo': {...}},
'phone': '1-770-736-8031 x56442',
'website': 'hildegard.org',
'company': { 'name': 'Romaguera-Crona',
'catchPhrase': 'Multi-layered client-server neural-net',
'bs': 'harness real-time e-markets'}}
>>> number_list = [123456789, 10000000000000]
>>> custom_printer.pprint(number_list)
[123_456_789, 10_000_000_000_000]
得到一個漂亮的字元串pformat()
如果您不想将漂亮的輸出發送到流怎麼辦? 進行一些正規表達式比對并替換某些鍵。
無論想對字元串預輸出做什麼, 可以使用 pformat() 擷取字元串:
>>>
>>> from pprint import pformat
>>> address = pformat(users[0]["address"])
>>> chars_to_remove = ["{", "}", "'"]
>>> for char in chars_to_remove:
... address = address.replace(char, "")
...
>>> print(address)
city: Gwenborough,
geo: lat: -37.3159, lng: 81.1496,
street: Kulas Light,
suite: Apt. 556,
zipcode: 92998-3874
pformat()是您可以使用的工具 在漂亮的列印機和輸出流之間切換。
另一個用例可能是,如果正在建構一個 API 并希望發送 JSON 字元串的漂亮字元串表示形式。
處理遞歸資料結構
- A有一個屬性 ,它指向 。.linkB
- B有一個屬性 ,它指向 。.linkA
如果虛遞歸函數無法處理這個循環引用, 則永遠不會完成列印!
>>>
>>> A = {}
>>> B = {"link": A}
>>> A["link"] = B
>>> print(A)
{'link': {'link': {...}}}
>>> from pprint import pprint
>>> pprint(A)
{'link': {'link': <Recursion on dict with id=3032338942464>}}
結論
- import 包使用pprint
- 使用 pprint() 代替正常print()
- 了解可用于自定義pprint所有參數
- 格式化的輸出字元串
- 建立 PrettyPrinter 的自定義執行個體
- 識别遞歸資料結構
#妙筆生花創作挑戰#