Python для начинающих
1.24K subscribers
546 photos
3 videos
232 files
74 links
Python для начинающих
Download Telegram
Как использовать zip и unpacking в Python
Как использовать zip и unpacking в Python: собираем пазл из данных

zip — это маленькая функция, которая решает кучу рутинных задач: объединяет списки, разворачивает таблицы, помогает красиво перебирать данные. А в паре с распаковкой (unpacking, оператор *) она становится особенно мощной.

---

## Базовое использование zip

zip “склеивает” несколько итерируемых объектов по позициям:

names = ["Alice", "Bob", "Charlie"]
scores = [95, 82, 78]

for name, score in zip(names, scores):
print(name, "=>", score)


Результат:

Alice => 95
Bob => 82
Charlie => 78


Важно: zip обрезает результат по самому короткому списку.

---

## Создание словаря из двух списков

Классический приём:

keys = ["host", "port", "debug"]
values = ["localhost", 8000, True]

config = dict(zip(keys, values))
print(config)


Результат:

{'host': 'localhost', 'port': 8000, 'debug': True}


---

## Unpacking: оператор * в действии

Оператор * “распаковывает” итерируемые объекты. В связке с zip это особенно полезно.

### Транспонирование “таблицы”

Представим матрицу как список строк:

matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]

transposed = list(zip(*matrix))
print(transposed)


Результат:

[(1, 4, 7), (2, 5, 8), (3, 6, 9)]


Мы как бы “повернули” таблицу: строки стали столбцами. Это один из самых элегантных трюков с zip.

---

## Распаковка результата zip

zip возвращает итератор, его тоже можно распаковать:

pairs = list(zip(names, scores))
print(pairs) # [('Alice', 95), ('Bob', 82), ('Charlie', 78)]

unzipped_names, unzipped_scores = zip(*pairs)
print(unzipped_names) # ('Alice', 'Bob', 'Charlie')
print(unzipped_scores) # (95, 82, 78)


Так можно “разобрать” список пар обратно на два отдельных набора данных.

---

## С enumerate и zip: удобный перебор

Иногда нужно и индекс, и значения из нескольких коллекций:

for idx, (name, score) in enumerate(zip(names, scores), start=1):
print(f"{idx}. {name}: {score}")


---

zip и unpacking — это инструменты, которые делают код короче, читабельнее и “питоничнее”. Освоив их, вы начнёте мыслить данными как блоками, которые легко собирать и разбирать, словно конструктор.
👍3🔥2
Работа с очередями с использованием модуля queue
Python для начинающих: работа с очередями через модуль queue

Если вам когда‑нибудь приходилось организовывать задачи «по очереди», то модуль queue — именно то, что нужно. Это стандартный модуль Python для безопасной работы с очередями в многопоточных программах. Но им удобно пользоваться и в обычных скриптах.

### Зачем нужна очередь?

Очередь (FIFO — first in, first out) — структура, которая забирает элементы в том же порядке, в котором они были добавлены. Это удобно для:

- обработки задач по мере поступления;
- организации «конвейеров» (один поток кладёт, другой забирает);
- ограничения количества элементов (защита от переполнения памяти).

### Базовый пример: Queue

from queue import Queue

task_queue = Queue(maxsize=3) # ограничим размер

task_queue.put("task_1")
task_queue.put("task_2")
task_queue.put("task_3")

print(task_queue.full()) # True

item = task_queue.get()
print("Got:", item)
print("Empty:", task_queue.empty())


Методы:
- put(item) — положить элемент (по умолчанию будет ждать, если очередь заполнена);
- get() — забрать элемент (будет ждать, если очередь пуста);
- full(), empty(), qsize() — состояние очереди.

### Очередь в многопоточности

queue.Queue уже потокобезопасна: можно спокойно использовать ее в разных потоках без дополнительных блокировок.

from queue import Queue
from threading import Thread
import time

task_queue = Queue()

def producer():
for i in range(5):
task = f"task_{i}"
print("Produce:", task)
task_queue.put(task)
time.sleep(0.2)
task_queue.put(None) # сигнал завершения

def consumer():
while True:
task = task_queue.get()
if task is None:
break
print("Consume:", task)
task_queue.task_done()

t1 = Thread(target=producer)
t2 = Thread(target=consumer)

t1.start()
t2.start()

t1.join()
t2.join()


Здесь:
- один поток «производит» задачи;
- второй их «потребляет»;
- None — маркер завершения работы.

### LIFO и приоритеты

Модуль queue умеет не только обычные очереди.

Стек (LIFO):

from queue import LifoQueue

stack = LifoQueue()
stack.put("first")
stack.put("second")

print(stack.get()) # second
print(stack.get()) # first


Очередь с приоритетом:

from queue import PriorityQueue

pq = PriorityQueue()
pq.put((2, "low"))
pq.put((1, "high"))
pq.put((3, "very_low"))

while not pq.empty():
priority, item = pq.get()
print(priority, item)


Элемент с наименьшим приоритетом (числом) будет обработан первым.

---

Модуль queue — это простой способ навести порядок в задачах и безопасно разделить работу между потоками. Даже если вы пока не лезете в сложную многопоточность, привычка использовать очереди поможет вам строить более чистую и предсказуемую архитектуру программ.
🔥4
Изучение структур данных: стек и очередь на Python
Изучение структур данных: стек и очередь на Python

Если вы пишете код «как-нибудь в списки», рано или поздно всё превращается в хаос. Структуры данных — это способ договориться с самим собой, как именно вы пользуетесь коллекцией. Сегодня разберём две классики: стек и очередь.

---

### Стек: принцип «последним пришёл — первым ушёл» (LIFO)

Стек — как стопка тарелок: снимаем сверху, кладём тоже сверху.

В Python стек удобно реализовать обычным списком:

stack = []

# push
stack.append(1)
stack.append(2)
stack.append(3)

print(stack) # [1, 2, 3]

# pop (снимаем с вершины)
top = stack.pop()
print(top) # 3
print(stack) # [1, 2]

# просмотр вершины без удаления
peek = stack[-1]
print(peek) # 2


Где это полезно:
- отмена действий (undo),
- обход деревьев,
- проверка правильности скобок в строке.

Мини‑пример проверки скобок:

def is_brackets_balanced(expr: str) -> bool:
stack = []
pairs = {')': '(', ']': '[', '}': '{'}
for ch in expr:
if ch in '([{':
stack.append(ch)
elif ch in ')]}':
if not stack or stack.pop() != pairs[ch]:
return False
return not stack

print(is_brackets_balanced("(a[b]{c})")) # True
print(is_brackets_balanced("(a[b]{c}")) # False


---

### Очередь: «первым пришёл — первым ушёл» (FIFO)

Очередь — как линия в супермаркете: обслуживают по порядку.

Наивный вариант через список:

queue = []
queue.append("task1")
queue.append("task2")
queue.append("task3")

first = queue.pop(0) # медленно на больших данных
print(first) # task1


Проблема: pop(0) сдвигает весь список, что дорого по времени. Для нормальной очереди используем collections.deque:

from collections import deque

queue = deque()

queue.append("task1")
queue.append("task2")
queue.append("task3")

first = queue.popleft()
print(first) # task1
print(queue) # deque(['task2', 'task3'])


deque оптимизирован под быстрые операции с обоих концов.

---

### Когда что использовать

- Стек — когда важно вернуться назад: история браузера, рекурсивные алгоритмы, разбор выражений.
- Очередь — когда задачи должны обрабатываться по мере поступления: обработка запросов, планирование задач, очереди сообщений.

Понимание этих двух структур — фундамент для более сложных: деревьев, графов, очередей с приоритетами. И да, в Python почти всегда достаточно list и deque, вопрос только в том, как вы их используете.
2👍1🔥1
Сериализация с помощью модуля pickle: плюсы и минусы
Сериализация с помощью pickle: плюсы и минусы

В какой‑то момент каждый питонист приходит к вопросу: как сохранить объект «как есть», а потом просто загрузить и продолжить работу? Стандартный ответ в мире Python — модуль pickle. Он умеет превращать почти любые объекты в байты и обратно. Но у этой магии есть цена.

---

### Что такое pickle?

pickle — это бинарный формат сериализации Python‑объектов.
То есть:

- сериализация — превращаем объект в байтовую строку;
- десериализация — восстанавливаем объект из байтов.

Простейший пример:

import pickle

data = {"user": "alice", "score": 42, "tags": ["python", "pickle"]}

with open("data.pkl", "wb") as f:
pickle.dump(data, f)

with open("data.pkl", "rb") as f:
loaded = pickle.load(f)

print(loaded)


Выглядит идеально: один модуль, одна строка — и ваш словарь переезжает на диск.

---

### Сильные стороны pickle

1. Работает «из коробки» почти со всем
Списки, словари, множества, пользовательские классы, вложенные структуры — pickle справится.

2. Минимум кода и усилий
Нет нужды вручную описывать поля, типы и схемы.

3. Удобен для быстрых прототипов и кэшей
Например, можно сохранить обученную модель или результат тяжёлых вычислений:

import pickle

class Model:
def __init__(self, weights):
self.weights = weights

model = Model(weights=[0.1, 0.5, 0.9])

with open("model.pkl", "wb") as f:
pickle.dump(model, f)

# ... позже
with open("model.pkl", "rb") as f:
restored_model = pickle.load(f)


---

### Обратная сторона: минусы и подводные камни

1. Опасность безопасности
Главное правило:

> Никогда не делайте pickle.load() на данных из непроверенного источника.

pickle может при десериализации выполнять произвольный код. Это не баг, а особенность протокола.

2. Формат специфичен для Python
Другие языки pickle не понимают. Обмениваться данными с внешними сервисами удобнее через JSON, Protobuf и т.п.

3. Хрупкость к изменению кода
Измените структуру класса — старые .pkl могут перестать корректно загружаться. Для долгосрочного хранения это риск.

4. Бинарный и нечитаемый
Нельзя просто открыть файл в редакторе и «глазами» понять, что внутри.

---

### Когда использовать pickle, а когда — нет?

Подходит:

- временные кэши;
- быстрые прототипы;
- сохранение внутренних объектов между запусками скрипта;
- сценарии, где и сохраняет, и загружает один и тот же контролируемый код.

Лучше избегать:

- всё, что связано с внешними пользователями;
- публичные API и сетевые протоколы;
- долгосрочное хранение важных данных;
- ситуации, где нужен человекочитаемый формат.

---

pickle — это мощный, но «острый» инструмент. Для внутренних задач разработчика он экономит часы работы. Для обмена данными и публичных сервисов чаще всего безопаснее и разумнее выбрать более строгие и переносимые форматы.
👍2🔥2
Создание простого cli-инструмента с аргументами через argparse
Создаём свой первый CLI-инструмент с argparse

Рано или поздно каждый питонист приходит к мысли: «Хочу свою консольную утилиту!» Что‑нибудь, что запускается из терминала, принимает аргументы и делает полезное дело. В Python для этого есть отличный модуль argparse.

---

### Зачем вообще нужны аргументы?

Без аргументов ваш скрипт живёт в режиме «одна команда — один результат». А с аргументами можно:

- менять режим работы (--verbose, --quiet)
- передавать файлы (--input file.txt)
- переключать формат вывода (--json, --text)

И всё это без изменения кода — просто другими параметрами запуска.

---

### Базовый пример: мини-калькулятор

Создадим файл calc.py, который принимает два числа и операцию:

import argparse

def main():
parser = argparse.ArgumentParser(
description="Simple CLI calculator"
)
parser.add_argument("a", type=float, help="First number")
parser.add_argument("b", type=float, help="Second number")
parser.add_argument(
"-o", "--operation",
choices=["add", "sub", "mul", "div"],
default="add",
help="Math operation (default: add)"
)

args = parser.parse_args()

if args.operation == "add":
result = args.a + args.b
elif args.operation == "sub":
result = args.a - args.b
elif args.operation == "mul":
result = args.a * args.b
elif args.operation == "div":
result = args.a / args.b

print(result)

if __name__ == "__main__":
main()


Теперь можно запускать:

python calc.py 2 3
python calc.py 10 5 -o sub
python calc.py 3 4 --operation mul


argparse уже умеет:

- показывать --help с описанием
- проверять типы (type=float)
- ограничивать значения (choices=[...])
- задавать значения по умолчанию (default=)

---

### Пара фишек, которые часто забывают

1. Флаг без значения — просто наличие/отсутствие:

parser.add_argument(
"-v", "--verbose",
action="store_true",
help="Show detailed output"
)


Теперь --verbose даёт args.verbose == True.

2. Переиспользование логики

Лучше выносить «деловую» логику в отдельные функции — тогда скрипт проще тестировать и расширять:

def calculate(a, b, operation):
if operation == "add":
return a + b
if operation == "sub":
return a - b
if operation == "mul":
return a * b
if operation == "div":
return a / b
raise ValueError("Unknown operation")


---

CLI-инструмент в Python — это буквально несколько строк с argparse, а ощущение уже как от «настоящей» утилиты. Попробуйте переписать свой следующий скрипт так, чтобы он принимал аргументы командной строки — разница в удобстве будет огромной.
👍3🔥1
Как работать с постраничной загрузкой данных из API
Python для начинающих: как подружиться с постраничной загрузкой из API

Если вы когда‑нибудь тянули данные из API, то почти наверняка сталкивались с ситуацией: «Тут 10 записей, а где остальные 10 000?». Ответ — в пагинации (postраничной загрузке). API редко отдают всё сразу, чтобы не положить ни себя, ни вас.

Разберёмся, какие бывают схемы пагинации и как с ними работать в Python.

---

### 1. Пагинация по номеру страницы

Классика: у вас есть page и per_page.

import requests

BASE_URL = "https://api.example.com/items"

def fetch_page(page: int, per_page: int = 50):
params = {"page": page, "per_page": per_page}
response = requests.get(BASE_URL, params=params, timeout=10)
response.raise_for_status()
return response.json()

def fetch_all_items():
page = 1
all_items = []
while True:
data = fetch_page(page)
items = data.get("items", [])
if not items:
break
all_items.extend(items)
if not data.get("has_next"): # или проверяем page >= total_pages
break
page += 1
return all_items


Ключевой момент — условие выхода. Часто API возвращает has_next, total_pages или next_page.

---

### 2. Пагинация по смещению (offset/limit)

Тут вам дают offset (сдвиг) и limit (размер пачки):

def fetch_batch(offset: int, limit: int = 100):
params = {"offset": offset, "limit": limit}
response = requests.get(BASE_URL, params=params, timeout=10)
response.raise_for_status()
return response.json()

def fetch_all_items_offset():
offset = 0
limit = 100
all_items = []
while True:
data = fetch_batch(offset, limit)
items = data.get("items", [])
if not items:
break
all_items.extend(items)
offset += limit
return all_items


Минус offset-подхода — при больших объёмах данных он может быть медленнее.

---

### 3. Пагинация по курсору (cursor / next)

Самый «современный» вариант: API возвращает ссылку или токен для следующей страницы.

def fetch_all_items_cursor():
url = BASE_URL
all_items = []
while url:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
items = data.get("items", [])
all_items.extend(items)
url = data.get("next") # None, если страниц больше нет
return all_items


Здесь нет ни страниц, ни offset — только next. Это устойчиво к изменениям данных на сервере.

---

### Полезные рекомендации

- Всегда ставьте timeout в requests.get.
- Уважайте лимиты API: иногда нужно делать time.sleep() между запросами.
- Логируйте прогресс: len(all_items) поможет понять, что вы действительно двигаетесь.

Понимая три паттерна пагинации — page, offset, cursor — вы сможете уверенно забирать из API тысячи и миллионы записей, не утонув ни в ошибках, ни в лимитах.
👍3
Работа с форматом YAML в Python с использованием PyYAML
Работа с форматом YAML в Python с использованием PyYAML

YAML любят за читаемость: в отличие от JSON, здесь меньше скобок и больше структуры за счёт отступов. Его часто используют для конфигов, docker-compose, GitHub Actions и т.д. Давайте посмотрим, как работать с YAML в Python с помощью библиотеки PyYAML.

Установка:

pip install pyyaml


---

## Базовая загрузка YAML

Пусть у нас есть файл config.yml:

app:
name: "MyApp"
debug: true
version: 1.0
database:
host: "localhost"
port: 5432
tags:
- primary
- readonly


Прочитаем его:

import yaml

with open("config.yml", "r", encoding="utf-8") as f:
config = yaml.safe_load(f)

print(config["app"]["name"]) # MyApp
print(config["database"]["tags"]) # ['primary', 'readonly']


safe_load — безопасный вариант парсинга, его и стоит использовать почти всегда.

---

## Запись данных в YAML

Сериализуем Python-объекты обратно в YAML:

import yaml

settings = {
"app": {"name": "NewApp", "debug": False},
"features": ["auth", "billing", "reports"]
}

with open("settings.yml", "w", encoding="utf-8") as f:
yaml.safe_dump(settings, f, sort_keys=False, allow_unicode=True)


Параметр sort_keys=False сохраняет порядок ключей, а allow_unicode=True позволяет писать не только ASCII.

---

## Работа со списками и вложенностью

PyYAML без проблем понимает сложные структуры:

import yaml

yaml_str = """
users:
- name: "Alice"
roles: ["admin", "editor"]
- name: "Bob"
roles:
- "viewer"
- "auditor"
"""

data = yaml.safe_load(yaml_str)

admins = [u["name"] for u in data["users"] if "admin" in u["roles"]]
print(admins) # ['Alice']


---

## Кастомные типы через теги

YAML поддерживает теги вроде !MyTag. С их помощью можно превращать YAML-данные сразу в объекты Python.

import yaml
from dataclasses import dataclass

@dataclass
class User:
name: str
level: int

def user_constructor(loader, node):
values = loader.construct_mapping(node)
return User(**values)

yaml.add_constructor("!User", user_constructor)

yaml_str = """
user: !User
name: "Alice"
level: 5
"""

data = yaml.safe_load(yaml_str)
print(data["user"]) # User(name='Alice', level=5)
print(data["user"].level) # 5


Так можно описывать конфиги, которые сразу превращаются в модели вашего приложения.

---

PyYAML — мощный и при этом простой инструмент: он позволяет читать и писать конфиги, работать со сложными структурами и даже маппить YAML на классы Python. Если вы часто имеете дело с настройками и инфраструктурой — эта библиотека станет обязательным пунктом в вашем наборе инструментов.
👍3🔥1
Изучение модуля sched: планирование задач во времени
Изучение модуля sched: планирование задач во времени

Большинство начинающих знают только time.sleep() и думают, что этим инструменты по работе со временем заканчиваются. Но в стандартной библиотеке Python есть модуль sched, который позволяет строить мини-планировщик задач — почти как будильник, но для кода.

### Зачем нужен sched?

sched удобен, когда нужно:

- выполнить задачу через некоторое время;
- запланировать серию событий;
- управлять порядком выполнения задач во времени.

При этом он не блокирует весь код сам по себе — вы сами решаете, когда запустить обработку событий.

### Базовый пример

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def say_hello(name):
print(f"Hello, {name}! Time:", time.time())

print("Start:", time.time())
scheduler.enter(3, 1, say_hello, argument=("Alice",))
scheduler.run()
print("End:", time.time())


Что здесь происходит:

- sched.scheduler(time.time, time.sleep) — создаем планировщик, который знает «что такое сейчас» и «как подождать».
- enter(delay, priority, action, argument=...) — выполняет action через delay секунд.
- scheduler.run() — запускает цикл обработки событий (блокирует поток до выполнения всех задач).

Через 3 секунды вы увидите приветствие и текущий timestamp.

### Приоритеты и несколько задач

priority пригодится, когда два события должны выполниться в одно и то же время.

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def log(msg):
print(time.time(), msg)

scheduler.enter(5, 2, log, argument=("low priority",))
scheduler.enter(5, 1, log, argument=("high priority",))

scheduler.run()


Обе задачи запланированы через 5 секунд, но сначала выполнится та, у которой priority=1.

### Отложенные и повторяющиеся задачи

Повторения можно организовать вручную — внутри функции заново планировать саму себя:

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def periodic_task(interval):
print("Tick at", time.time())
scheduler.enter(interval, 1, periodic_task, argument=(interval,))

scheduler.enter(1, 1, periodic_task, argument=(2,))
scheduler.run()


Здесь первая задача стартует через 1 секунду, а затем каждые 2 секунды перепланирует себя.

### Когда использовать sched, а когда нет

sche­d хорош для:

- простого планирования задач в одном потоке;
- тестов и симуляций событий во времени;
- ситуаций, где нужен контроль над порядком выполнения и временем.

Если нужно:

- сложное расписание (крон-подобное);
- работа с разными часовыми поясами, датами, календарями;
- продвинутая асинхронность,

то лучше посмотреть в сторону APScheduler, asyncio или системного cron.

Но для понимания базовых принципов планирования задач во времени sched — идеальный старт, да еще и без сторонних библиотек.
👍4
Инструменты отладки кода: использование модуля pdb
Инструменты отладки кода: знакомство с модулем pdb

Большинство новичков отлаживают код методом «print по всему файлу». Это работает, пока проект маленький. Но как только логика усложняется, принты превращают код в хаос. Пора знакомиться с встроенным отладчиком Python — модулем pdb.

---

## Что такое pdb и зачем он нужен

pdb позволяет:
- ставить точки останова (breakpoints);
- пошагово выполнять код;
- смотреть значения переменных «изнутри» функции;
- менять состояние программы на лету.

И все это — прямо в терминале, без IDE.

---

## Базовый пример: pdb.set_trace()

Допустим, у нас странная функция, которая считает среднее, но иногда падает с ошибкой:

import pdb

def avg(values):
total = 0
count = 0
for v in values:
total += v
count += 1
return total / count

data = [10, 20, 0, "oops", 40]

pdb.set_trace() # точка останова
result = avg(data)
print(result)


Запускаем:

python script.py


На строке с set_trace() программа остановится, и вы увидите приглашение вида:

(Pdb)


Теперь можно управлять выполнением.

---

## Минимальный набор команд pdb

Внутри отладчика доступны команды:

- l — (list) показать код вокруг текущей строки;
- n — (next) выполнить следующую строку в текущей функции;
- s — (step) шаг внутрь вызываемой функции;
- c — (continue) продолжить выполнение до следующего breakpoint;
- p expr — (print) напечатать выражение, например p data;
- q — (quit) выйти из отладчика.

Например, из нашего примера:

(Pdb) p data
[10, 20, 0, 'oops', 40]
(Pdb) n


Можно зайти внутрь avg:

(Pdb) s


И уже там:

(Pdb) p v
10
(Pdb) n
(Pdb) p total
10


Так легко найти момент, когда v внезапно становится строкой "oops" и ломает вычисления.

---

## Breakpoint без импорта: встроенная функция breakpoint()

Начиная с Python 3.7 есть удобный шорткат:

def calc_sum(values):
s = 0
for v in values:
s += v
return s

data = [1, 2, 3]
breakpoint() # работает как pdb.set_trace() по умолчанию
print(calc_sum(data))


Функция breakpoint() смотрит на переменную окружения PYTHONBREAKPOINT, поэтому при желании можно подменять стандартный отладчик.

---

## Отладка конкретного файла через -m pdb

Иногда не хочется править код и вставлять set_trace(). Можно запустить файл целиком через pdb:

python -m pdb script.py


pdb сразу загрузит файл, поставит breakpoint на первой строке, и дальше вы будете управлять выполнением командами n, s, c и т.д.

---

pdb — это минимальный, но мощный инструмент, который стоит освоить как можно раньше. Он дисциплинирует мышление: вместо хаотичных принтов вы начинаете осознанно исследовать состояние программы и понимать, почему она ведет себя так, а не иначе.
3👍1
Как работать с цветом в терминале: библиотека colorama
Как работать с цветом в терминале: библиотека colorama

Текстовый вывод в консоль необязательно должен быть скучным. Цвет помогает выделять ошибки, предупреждения, важные шаги и просто делает скрипт понятнее. В Python это удобно делать с помощью библиотеки colorama.

---

## Установка и базовое использование

Установим библиотеку:

pip install colorama


Минимальный пример:

from colorama import init, Fore, Back, Style

init(autoreset=True)

print(Fore.RED + "Error: something went wrong")
print(Fore.GREEN + "Success: all tests passed")
print(Back.YELLOW + Fore.BLACK + "Warning: check your settings")
print(Style.DIM + "This is a dim text")
print(Style.BRIGHT + "This is a bright text")


init(autoreset=True) автоматически сбрасывает цвет после каждой строки, чтобы не красить весь терминал случайно.

---

## Ручной контроль сброса

Если нужно более тонко управлять стилем:

from colorama import init, Fore, Style

init(autoreset=False)

print(Fore.CYAN + "Step 1:", Style.RESET_ALL, "download data")
print(Fore.MAGENTA + "Step 2:", Style.RESET_ALL, "process data")

print(Fore.RED + "Critical message", end="")
print(Style.RESET_ALL) # сбросили только здесь


Так можно красить только часть строки и точно контролировать, где стиль заканчивается.

---

## Цветной логгер своими руками

Сделаем простой цветной вывод по уровням:

from colorama import init, Fore, Style

init(autoreset=True)

def log(message, level="info"):
if level == "info":
color = Fore.CYAN
elif level == "warning":
color = Fore.YELLOW
elif level == "error":
color = Fore.RED + Style.BRIGHT
else:
color = Fore.WHITE

print(color + f"[{level.upper()}] {message}")

log("Application started", "info")
log("Low disk space", "warning")
log("Unable to connect to database", "error")


Такой мини-логгер уже заметно улучшает читаемость вывода, особенно в длинных скриптах.

---

## Кроссплатформенность

Главный плюс colorama — он одинаково работает:

- на Windows (преобразует ANSI-коды в понятные для консоли команды),
- в Linux и macOS (где ANSI уже поддерживаются).

То есть вы один раз пишете цветной вывод — и не думаете о том, на какой системе будет запускаться ваш скрипт.

---

Попробуйте добавить colorama в свои маленькие утилиты: подсветите ошибки, выделите успешные шаги, сделайте прогресс более наглядным. Цвет в консоли — это простой инструмент, который заметно повышает удобство работы с программой.
👍5