2

10 минут кода: Расширяем возможности `pprint()`

Привет!  Я покажу о свою реализацию функции pprint(). Это простая функция, которая помогает сделать вывод данных в консоль более читаемым. Когда у тебя есть сложные структуры, например, большие словари, списки или объекты pprint() «красиво» выводит их на экран. Функция также выводит на экран N строк текстовых файлов

pprint(dict)

pprint(list)

pprint(Object)

pprint('text.txt', max_lines=10)

и получить данные в «читабельном» виде.

сразу код функции:


import json

import csv

import pandas as pd

from pathlib import Path

from typing import Any

from pprint import pprint as pretty_print


def pprint(print_data: str | list | dict | Path | Any = None, depth: int = 4, max_lines: int = 10, *args, **kwargs) -> None:

""" Pretty prints the given data in a formatted way.


The function handles various data types and structures such as strings, dictionaries, lists, objects, and file paths.

It also supports reading and displaying data from CSV and XLS/XLSX files.


Args:

print_data (str | list | dict | Any, optional): The data to be printed. It can be a string, dictionary, list, object, or file path. Defaults to `None`.

depth (int, optional): The depth to which nested data structures will be printed. Defaults to 4.

max_lines (int, optional): Maximum number of lines to print from a file (CSV/XLS). Defaults to 10.

*args: Additional positional arguments passed to the print or pretty_print function.

**kwargs: Additional keyword arguments passed to the print or pretty_print function.


Returns:

None: The function prints the formatted output and does not return any value.


Example:

>>> pprint("/path/to/file.csv", max_lines=5)

>>> pprint("/path/to/file.xls", max_lines=3)

"""

if not print_data:

return


def _read_text_file(file_path: str | Path, max_lines: int) -> list | None:

"""Reads the content of a text file up to `max_lines` lines."""

path = Path(file_path)

if path.is_file():

try:

with path.open("r", encoding="utf-8") as file:

return [file.readline().strip() for _ in range(max_lines)]

except Exception as ex:

pretty_print(print_data)

return None


def _print_class_info(instance: Any, *args, **kwargs) -> None:

"""Prints class information including class name, methods, and properties."""

class_name = instance.__class__.__name__

class_bases = instance.__class__.__bases__


print(f"Class: {class_name}", *args, **kwargs)

if class_bases:

print([base.__name__ for base in class_bases], *args, **kwargs)


attributes_and_methods = dir(instance)

methods = []

properties = []


for attr in attributes_and_methods:

if not attr.startswith('__'):

try:

value = getattr(instance, attr)

except Exception:

value = "Error getting attribute"

if callable(value):

methods.append(f"{attr}()")

else:

properties.append(f"{attr} = {value}")


pretty_print("Methods:", *args, **kwargs)

for method in sorted(methods):

pretty_print(method, *args, **kwargs)

print("Properties:", *args, **kwargs)

for prop in sorted(properties):

pretty_print(prop, *args, **kwargs)


def _print_csv(file_path: str, max_lines: int) -> None:

"""Prints the first `max_lines` lines from a CSV file."""

try:

with open(file_path, newline='', encoding='utf-8') as csvfile:

reader = csv.reader(csvfile)

header = next(reader)

print(f"CSV Header: {header}")

for i, row in enumerate(reader, start=1):

print(f"Row {i}: {row}")

if i >= max_lines:

break

except Exception as ex:

pretty_print(print_data)


def _print_xls(file_path: str, max_lines: int) -> None:

"""Prints the first `max_lines` rows from an XLS/XLSX file."""

try:

df = pd.read_excel(file_path, nrows=max_lines)

print(df.head(max_lines).to_string(index=False))

except Exception as ex:

pretty_print(print_data)


def json_serializer(obj):

"""Custom handler for unsupported data types in JSON."""

if isinstance(obj, Path):

return str(obj)


# Check if it's a file path

if isinstance(print_data, str):

if Path(print_data).is_file():

file_extension = Path(print_data).suffix.lower()


if file_extension == '.csv':

_print_csv(print_data, max_lines)

elif file_extension in ['.xls', '.xlsx']:

_print_xls(print_data, max_lines)

elif file_extension == '.txt':

content = _read_text_file(print_data, max_lines)

if content:

for line in content:

print(line)

elif file_extension == '.json':

try:

with open(print_data, 'r', encoding='utf-8') as json_file:

json_data = json.load(json_file)

print(json.dumps(json_data, default=json_serializer, indent=4))

except Exception as ex:

pretty_print(print_data)

else:

pretty_print(print_data, *args, **kwargs)

else:

# If the data is not a file, pretty print or handle it as a class

try:

if isinstance(print_data, dict):

print(json.dumps(print_data, default=json_serializer, indent=4))

elif isinstance(print_data, list):

print("[")

for item in print_data:

print(f"\t{item} - {type(item)}")

print("]")

else:

print(print_data, *args, **kwargs)

if hasattr(print_data, '__class__'):

_print_class_info(print_data, *args, **kwargs)

except Exception as ex:

pretty_print(print_data)

код на github

gist

Для запуска и проверки кода я сделал Интерактивный блокнот google colab

Как работает функция:

  1. Печать строковых данных**: Если предоставленный аргумент является строкой, функция проверяет, представляет ли она путь к файлу. Если это так, функция считывает содержимое файла и выводит его. Если строка не является путем к файлу, функция просто выводит строку.

  2. Печать списков**: Если аргумент является списком, функция преобразует все объекты `Path` в списке в строки и использует стандартную функцию `pprint` для форматирования списка.

  3. Печать словарей**: Если аргумент является словарем, функция преобразует все объекты `Path` в строки, чтобы обеспечить корректную сериализацию в JSON. Затем она выводит словарь в формате JSON с отступами для повышения читаемости

  4. Печать объектов**: Если аргумент является объектом, функция использует `pprint`, чтобы вывести объект вместе с дополнительной информацией о его классе, методах и свойствах. Функция выводит имя класса, его базовые классы и перечисляет методы и свойства объекта, упрощая анализ его структуры.

  5. Вывод в консоль произвольное количество сток из тексовых файлов (txt, json,csv,xls)

Примеры.

Все примеры можно запускать в блокноте jupyter notebook https://colab.research.google.com/drive/1uBcZuMabkix2qpNJtNk...
Здеськраткое руководство как пользоваться блокнотом

Пример 1: Строка

pprint("Hello, World!")

Результат:

'Hello, World!'

Пример 2.1: Список

from pathlib import Path

example_list = [

"Hello, World!",

Path("C:/example/path"),

42,

{"key": "value"}

]

example_list_2 = [

"Python is fun!",

Path("/home/user/project"),

99,

{

"name": "Alice",

"age": 30,

"languages": ["Python", "JavaScript", "C++"]

}

]

pprint(example_list)

Результат:

[

Hello, World! - <class 'str'>

C:/example/path - <class 'pathlib.PosixPath'>

42 - <class 'int'> {'key': 'value'} - <class 'dict'>

[1, 2, 3] - <class 'list'>

]

Пример 2.2: Несколько списков

pprint(example_list+example_list_2)

Результат:

[

Hello, World! - <class 'str'>

C:/example/path - <class 'pathlib.PosixPath'>

42 - <class 'int'> {'key': 'value'} - <class 'dict'>

Python is fun! - <class 'str'>

/home/user/project - <class 'pathlib.PosixPath'>

99 - <class 'int'>

{'name': 'Alice', 'age': 30, 'languages': ['Python', 'JavaScript', 'C++']} - <class 'dict'>

]

Пример 3: Словарь

from pathlib import Path

import json

example_dict = {

"name": "Alice",

"age": 30,

"address": {

"street": "123 Main St",

"city": "Wonderland"

},

"files": [Path("C:/file1.txt"), Path("C:/file2.txt")]

}

pprint(example_dict)

Результат:

{

{

"name": "Alice",

"age": 30,

"address":{

"street": "123 Main St",

"city": "Wonderland"

},

"files": [ "C:/file1.txt", "C:/file2.txt" ]

}

Пример 4.1: Объект класса MyClass

class MyClass:

def __init__(self, name, value):

self.name = name

self.value = value

def display(self):

return f"{self.name} has value {self.value}"

# Create an instance of the class

obj = MyClass(name="TestObject", value=100)

# Print object information

pprint(obj)

Результат:

<__main__.MyClass object at 0x797a27f17b50>

Class: MyClass

['object']

'Methods:'

'display()'

Properties:

'name = TestObject'

'value = 100'

Пример 4.2: Объект класса Path

import os

from pathlib import Path

current_path = Path(os.getcwd()).resolve()

pprint(current_path)

Результат:

/content

Class: PosixPath

['Path', 'PurePosixPath']

'Methods:'

...

'absolute()'

'as_posix()'

'as_uri()'

'chmod()'

'cwd()'

'exists()'

'expanduser()'

'glob()'

'group()'

'hardlink_to()'

'home()'

...

Properties:

...

'anchor = /'

'drive = '

'name = content'

'parent = /'

'parents = <PosixPath.parents>'

"parts = ('/', 'content')"

'root = /'

'stem = content'

'suffix = '

'suffixes = []'

Пример 5: печать содержимого файла JSON

import json

from pathlib import Path

dct = {

"имя": "Руслан",

"возраст": 25,

"город": "Москва",

"навыки": ["Python", "Наука о данных"]

}

# Save the dictionary to a JSON file

with open(Path('example_json.json'), 'w', encoding='utf-8') as f:

json.dump(dct, f, ensure_ascii=False, indent=4)

# Pretty print the JSON file

pprint('example_json.json')

Результат:

{

"имя": "Руслан",

"возраст": 25,

"город": "Москва",

"навыки": [ "Python", "Наука о данных" ]

}

Пример 6: печать первых 10 строк из файла ТХТ

from pathlib import Path


s = """1: В лесу родилась ёлочка,

2: В лесу она росла.

3: Зимой и летом стройная,

4: Зелёная была.


5: Метель ей пела песенку:

6: «Спи, ёлочка, бай-бай!»

7: Мороз снежком укутывал:

8: «Смотри, не замерзай!»


9: Трусишка зайка серенький

10: Под ёлочкой скакал.

11: Порою волк, сердитый волк,

12: Рысцою пробегал.


13: Чу! Снег по лесу частому

14: Под полозом скрипит.

15: Лошадка мохноногая

16: Торопится, бежит."""


# Save text file

with open(Path('example_txt.txt'), 'w', encoding='utf-8') as f:

f.write(s)

max_lines=10 # <- количество выводимых на печать строк

# Call pprint with the correct filename

pprint('example_txt.txt', max_lines=max_lines)

Результат:

1: В лесу родилась ёлочка,

2: В лесу она росла.

3: Зимой и летом стройная,

4: Зелёная была.

5: Метель ей пела песенку:

6: «Спи, ёлочка, бай-бай!»

7: Мороз снежком укутывал:

8: «Смотри, не замерзай!»

Пример 7: печать первых двух строк из файла CSV

import csv

from pathlib import Path


# Содержимое example.csv:

csv_data = """имя,возраст,город

Алексей,30,Москва

Борис,25,Санкт-Петербург

Виктор,35,Казань

Дмитрий,28,Новосибирск

Екатерина,22,Екатеринбург

"""

# Создание CSV файла

with open(Path('example.csv'), 'w', encoding='utf-8') as f:

f.write(csv_data)

pprint('example.csv', max_lines=2)

Результат:

CSV Header: ['имя', 'возраст', 'город']

Row 1: ['Алексей', '30', 'Москва']

Row 2: ['Борис', '25', 'Санкт-Петербург']

Пример 8: печать первых трёх строк из файла XLS

import pandas as pd

from pathlib import Path

# Create a sample DataFrame and save it as an Excel file

data = {

"имя": "Руслан",

"возраст": 25,

"город": "Москва",

"навыки": ["Python", "Наука о данных"]

}

df = pd.DataFrame(data)

# Save the DataFrame as an .xlsx file

df.to_excel('example.xlsx', index=False)

# Print the file name using pprint

pprint('example.xlsx', max_lines=3)

Результат:

имя возраст город навыки

Руслан 25 Москва Python

Руслан 25 Москва Наука о данных

Для запуска и проверки кода я сделал Интерактивный блокнот google colab. здесь все наглядно с примерами

Программирование на python

884 поста11.9K подписчиков

Правила сообщества

Публиковать могут пользователи с любым рейтингом. Однако!


Приветствуется:

• уважение к читателям и авторам

• конструктивность комментариев

• простота и информативность повествования

• тег python2 или python3, если актуально

• код публиковать в виде цитаты, либо ссылкой на специализированный сайт


Не рекомендуется:

• допускать оскорбления и провокации

• распространять вредоносное ПО

• просить решить вашу полноценную задачу за вас

• нарушать правила Пикабу