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

Привет, меня зовут Иван, и сегодня мы поговорим о PEP8 — вашем надежном компасе в мире чистого Python-кода. Возможно, вы уже слышали: “Пишите читаемый код!”, “Соблюдайте стиль!”. Но что за стиль, и зачем он вообще нужен? Давайте разберёмся.

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

PEP8 — это стиль кодирования, одобренный Python-сообществом. Его цель — сделать код понятным не только вам, но и вашим коллегам. Представьте код с разным отступом, непонятными именами, хаотичными пробелами — это как лабиринт. PEP8 превращает этот лабиринт в аккуратную дорогу.

## Главные правила PEP8

### Отступы

Используйте 4 пробела на каждый уровень вложенности. Табуляции? Забываем! Python обожает пробелы:

def greet(name):
print(f"Hello, {name}!")


### Имена переменных и функций

Функции и переменные — маленькие змейки: snake_case. Классы — CamelCase:

def calculate_area(radius):
return 3.14 * radius ** 2

class CircleAreaCalculator:
pass


### Пробелы

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

x = 1  # правильно
y=2 # неправильно!
z = y+1 # тоже нехорошо


### Длина строки

PEP8 рекомендует не превышать 79 символов в строке. Во-первых, код помещается на экран. Во-вторых, не приходится горизонтально скроллить:

result = magic_function(param1, param2, param3, param4, param5, param6)


Если длинно — переносим:

result = magic_function(
param1, param2, param3, param4,
param5, param6
)


### Импортируем красиво

Импорты — с новых строк. Сначала стандартные модули, потом сторонние, потом ваши собственные:

import os
import sys

import requests

from mymodule import my_function


## Проверяем себя

Хватит ли помнить все правила наизусть? Нет. Используйте автоматические инструменты:
- flake8 — проверяет стиль кода
- black — автоматически форматирует код

## Заключение

PEP8 — не занудное ограничение, а инструмент вашего профессионализма. Чистый код экономит время, спасает нервы и даже делает друзей! Не стесняйтесь открывать PEP8 чаще обычного — и ваш Python будет не только работать, но и радовать глаз.
👍2
Работа с аудиофайлами: основное введение в модуль wave
Работа с аудиофайлами: основное введение в модуль wave
Работа с аудиофайлами: основное введение в модуль wave

Представьте, что вы хотите прочитать или обработать аудиофайл формата WAV в Python. Где-то на жестком диске томно покоится классическая мелодия “Moonlight.wav”, и вашей задачей становится: узнать её параметры или скопировать пару секунд звука в новый файл. Как это сделать? Представляю простое, но очень полезное оружие из стандартной библиотеки — модуль wave.

### В чём суть формата WAV?

WAV — это контейнер для хранения необработанных (raw) аудиоданных, обычно с минимальным сжатием. Как правило, это PCM-звук: каждая секунда — это тысячи отсчётов-чисел, определяющих амплитуду сигнала.

### Простое чтение WAV-файла

Модуль wave позволяет безопасно заглянуть внутрь файла и считать метаданные: количество каналов, частоту дискретизации и длину.

import wave

with wave.open('Moonlight.wav', 'rb') as audio:
n_channels = audio.getnchannels()
sample_width = audio.getsampwidth()
frame_rate = audio.getframerate()
n_frames = audio.getnframes()
duration = n_frames / frame_rate

print(f'Channels: {n_channels}')
print(f'Sample width: {sample_width} bytes')
print(f'Frame rate: {frame_rate} Hz')
print(f'Duration: {duration:.2f} seconds')


Всё, что между with ... as audio:, работает с открытым файлом: считаем параметры и даже узнаём длительность!

### Извлечение и сохранение кусочка аудио

Допустим, нужно вырезать первые 5 секунд аудио и записать их в новый WAV файл.

import wave

with wave.open('Moonlight.wav', 'rb') as original:
frame_rate = original.getframerate()
n_frames_to_copy = frame_rate * 5
frames = original.readframes(n_frames_to_copy)

with wave.open('Snippet.wav', 'wb') as snippet:
snippet.setnchannels(original.getnchannels())
snippet.setsampwidth(original.getsampwidth())
snippet.setframerate(frame_rate)
snippet.writeframes(frames)


Модуль wave работает только с несжатым PCM-звуком, но зато позволяет управлять WAV-файлами без лишних зависимостей.

### Секреты и ограничения модуля wave

wave — это абсолютный минималист. Он не умеет работать с mp3/flac и не воспроизводит звук. Но если хочется быстро проанализировать структуру WAV или сделать простейшее редактирование, — это именно ваш инструмент.

Используйте wave, если вам нужно: узнать, как устроена “под капотом” музыка, или написать свою первую аудиопрограмму на Python!
1👍1
- Как организовать модульную структуру проекта Python с помощью init.py.
- Как организовать модульную структуру проекта Python с помощью init.py.
Python для начинающих: как приручить __init__.py и навести порядок в проекте

Когда скрипт разрастается до 500+ строк, появляется соблазн «просто дописать еще чуть-чуть». А потом — боль: сложно найти нужную функцию, тестировать, переиспользовать код. Время знакомиться с модульной структурой и файлом __init__.py.

---

### Что такое пакет и зачем нужен __init__.py

Пакет — это просто папка с Python-кодом, которую интерпретатор воспринимает как модуль. Классический пакет содержит:

my_app/
__init__.py
models.py
services.py
utils/
__init__.py
validators.py
formatters.py


Наличие __init__.py говорит Python: «это пакет, его можно импортировать».

---

### Простейший пример: группируем логику

Пусть у нас мини-приложение для работы с пользователями.

my_app/models.py:

class User:
def __init__(self, username: str):
self.username = username


my_app/services.py:

from .models import User

def create_user(username: str) -> User:
return User(username=username)


Теперь сделаем пакет удобным с помощью __init__.py.

my_app/__init__.py:

from .models import User
from .services import create_user

__all__ = ["User", "create_user"]


Теперь в основном скрипте:

from my_app import User, create_user

user = create_user("alice")
print(user.username)


Мы спрятали внутреннюю структуру (файлы models.py, services.py), оставив аккуратный публичный интерфейс.

---

### Вложенные пакеты и точечный импорт

Добавим утилиты:

my_app/utils/validators.py:

def is_valid_username(username: str) -> bool:
return len(username) >= 3


my_app/utils/__init__.py:

from .validators import is_valid_username

__all__ = ["is_valid_username"]


И обновим my_app/__init__.py:

from .models import User
from .services import create_user
from .utils import is_valid_username

__all__ = ["User", "create_user", "is_valid_username"]


Теперь в любом месте проекта:

from my_app import is_valid_username

print(is_valid_username("ab")) # False
print(is_valid_username("alex")) # True


---

### Зачем вообще заморачиваться с __init__.py

1. Чистый публичный API
Через __all__ вы явно решаете, что можно импортировать снаружи, а что считается «внутренней кухней».

2. Сокрытие структуры
Можно переименовать файл services.py в logic.py, не ломая внешний код — если __init__.py сохраняет те же имена.

3. Удобные групповые импорты
Вместо:

   from my_app.models import User
from my_app.services import create_user


достаточно:

   from my_app import User, create_user


4. Инициализация пакета
В __init__.py можно разместить код, который выполнится при первом импорте пакета: настройка логгера, загрузка конфигурации (без фанатизма).

---

### Маленькое правило напоследок

Если модулей становится слишком много, и __init__.py превращается в свалку импортов — это сигнал, что пакет пора логически разбивать дальше. Хорошая структура проекта — та, где содержимое видно «с первого взгляда», а __init__.py помогает, а не запутывает.
👍1
- Создание базового TCP-сервера с использованием сокетов Python.
Создание базового TCP‑сервера с использованием сокетов Python

Иногда хочется почувствовать себя чуть ближе к «низам» интернета — туда, где нет Flask и Django, а есть только чистые сокеты и байты. Давайте напишем свой минимальный TCP‑сервер и разберёмся, что вообще происходит «под капотом».

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

Сокет — это конечная точка сетевого соединения. У простого TCP-сервера есть три основных шага:

1. Создать сокет.
2. Привязать его к адресу и порту.
3. Слушать входящие подключения и обрабатывать клиентов.

Используем стандартный модуль socket.

### Самый простой TCP‑сервер

Напишем сервер, который принимает соединение и отсылает клиенту приветствие:

import socket

HOST = "127.0.0.1" # localhost
PORT = 5000 # любой свободный порт > 1024

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1) # максимальная очередь из 1 клиента

print(f"Server is listening on {HOST}:{PORT}...")

conn, addr = server_socket.accept()
print(f"Connected by {addr}")

message = "Hello from TCP server!\n"
conn.sendall(message.encode("utf-8"))

conn.close()
server_socket.close()


Кратко по шагам:

- socket.AF_INET — IPv4;
- socket.SOCK_STREAM — протокол TCP;
- bind — говорим ОС: «Этот сервер живёт на HOST:PORT»;
- listen — включаем режим ожидания подключений;
- accept — блокируется, пока клиент не подключится, и возвращает новый сокет conn только для этого клиента.

Проверить можно через telnet 127.0.0.1 5000 или написать маленького клиента.

### Эхо‑сервер: отвечаем на сообщения

Сделаем сервер, который читает данные от клиента и отправляет их обратно:

import socket

HOST = "127.0.0.1"
PORT = 5001

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(5)
print(f"Echo server on {HOST}:{PORT}")

while True:
conn, addr = server_socket.accept()
print(f"Client connected: {addr}")
with conn:
while True:
data = conn.recv(1024) # читаем до 1024 байт
if not data:
break # клиент закрыл соединение
print(f"Received: {data!r}")
conn.sendall(data) # отправляем назад


Здесь важно:

- recv возвращает bytes; пустые b"" означают разрыв соединения;
- sendall гарантирует отправку всего буфера;
- цикл while True позволяет обслуживать клиентов один за другим.

### О чём стоит помнить

- Порт должен быть свободен, иначе будет ошибка OSError: [Errno 98] Address already in use.
- При разработке удобно использовать 127.0.0.1, для внешнего доступа — "0.0.0.0".
- Такой сервер однопоточен: пока он общается с одним клиентом, другие ждут. Для реальных задач нужны потоки (threading) или asyncio.

Через такие простые примеры становится понятнее, что веб‑фреймворки всего лишь надстройка над таким же socket, который вы сейчас написали сами.
👍3
- Как настроить воркфлоу автоматизации на GitHub Actions для Python-проекта.
Как настроить GitHub Actions для Python-проекта: CI за 10 минут

Ты пишешь код, пушишь его в репозиторий… и только потом вспоминаешь, что не запустил тесты. Классика. GitHub Actions решает эту проблему: он запускает проверки автоматически при каждом коммите или pull request.

Разберём минимальный, но полезный воркфлоу для Python.

---

### Шаг 1. Структура проекта

Допустим, у тебя такой проект:

.
├─ src/
│ └─ main.py
├─ tests/
│ └─ test_main.py
├─ requirements.txt
└─ pyproject.toml (или setup.cfg / setup.py — не критично)


tests/ — место для тестов, requirements.txt — зависимости.

---

### Шаг 2. Пишем простой код и тест

src/main.py:

def add(a: int, b: int) -> int:
return a + b


tests/test_main.py:

from src.main import add


def test_add_positive():
assert add(2, 3) == 5


def test_add_negative():
assert add(-1, -3) == -4


Добавь pytest в requirements.txt:

pytest==8.3.0


---

### Шаг 3. Создаём воркфлоу GitHub Actions

В репозитории создай папку .github/workflows/ и файл, например python-ci.yml.

name: Python CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
tests:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.10", "3.11"]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Run tests
run: pytest -q


Что тут происходит:

- on — когда запускать воркфлоу: при push и pull_request в main.
- matrix — прогоняем тесты на нескольких версиях Python.
- actions/checkout — забирает код из репозитория.
- actions/setup-python — ставит нужную версию Python.
- Install dependencies — ставим зависимости.
- Run tests — запускаем pytest.

---

### Шаг 4. Бонус: проверка стиля

Добавим линтер flake8:

requirements.txt:

pytest==8.3.0
flake8==7.1.0


И ещё один шаг в воркфлоу:

      - name: Lint with flake8
run: |
flake8 src tests


Теперь каждый коммит проходит:

1. Установку зависимостей
2. Линтер
3. Тесты на нескольких версиях Python

Если что-то падает — GitHub подсветит это прямо в Pull Request.

---

GitHub Actions превращает твой репозиторий в маленький конвейер качества: ты пишешь код — он сам проверяет, что ты ничего не сломал. Настроить один раз — экономить часы и нервы постоянно.
👍2
- Введение в matplotlib: базовые графики и настройка их стилей.
Введение в matplotlib: базовые графики и стильные фишки

Matplotlib — это как карандаш для программиста: без него работать можно, но рисовать данные неудобно. Библиотека умеет строить почти любые графики, а начинать лучше с простого: линейных, точечных и столбчатых диаграмм.

---

### Первый график за 5 строк

Установите библиотеку (если нужно):

pip install matplotlib


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

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 3, 5, 7]

plt.plot(x, y)
plt.title("Simple line plot")
plt.xlabel("X axis")
plt.ylabel("Y axis")
plt.show()


plot — линия, title — заголовок, xlabel/ylabel — подписи осей, show — вывод окна с графиком.

---

### Цвета, маркеры и стили линий

Matplotlib позволяет легко “приодеть” график:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y1 = [1, 4, 9, 16]
y2 = [2, 3, 2, 3]

plt.plot(x, y1, color="red", linestyle="--", marker="o", label="squares")
plt.plot(x, y2, color="#008080", linestyle="-.", marker="s", label="wavy")

plt.title("Styled lines")
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.grid(True)
plt.show()


Что полезно запомнить:
- color: "red", "green", "black" или HEX "#008080".
- linestyle: "-", "--", "-.", ":".
- marker: "o", "s", "x", "^" и др.
- legend() — показывает легенду по label.

---

### Точечные и столбчатые графики

Для разброса точек используйте scatter:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [5, 3, 4, 2, 1]

plt.scatter(x, y, color="purple", s=80, alpha=0.7)
plt.title("Scatter plot")
plt.xlabel("X")
plt.ylabel("Y")
plt.grid(True)
plt.show()


Параметры: s — размер точек, alpha — прозрачность.

Столбчатая диаграмма:

import matplotlib.pyplot as plt

labels = ["Mon", "Tue", "Wed", "Thu", "Fri"]
values = [10, 12, 9, 15, 11]

plt.bar(labels, values, color="orange")
plt.title("Weekly stats")
plt.ylabel("Value")
plt.show()


---

### Быстрая смена стиля оформления

Matplotlib поддерживает готовые стили:

import matplotlib.pyplot as plt

plt.style.use("ggplot") # попробуйте также "seaborn-v0_8", "dark_background"

x = [1, 2, 3, 4]
y = [3, 8, 1, 10]

plt.plot(x, y, marker="o")
plt.title("Styled with ggplot")
plt.show()


Один вызов plt.style.use — и у вас другой фон, сетка и палитра.

---

Matplotlib хорош тем, что простой код уже даёт читабельные графики, а добавляя по одному параметру — цвет, легенду, стиль — вы постепенно превращаете “сырой” график в понятную визуализацию.
👍3
- Как использовать модуль argparse для разбор параметров CLI.
Как подружиться с argparse и сделать свой первый CLI-инструмент

Почти каждый полезный скрипт рано или поздно превращается в маленькую консольную утилиту: нужно передать путь к файлу, режим работы, уровень логирования. Пихать всё в input() — путь страданий. Для этого в стандартной библиотеке есть модуль argparse, который превращает ваш скрипт в удобный CLI-инструмент с автогенерируемой справкой.

---

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

Скрипт, который приветствует пользователя по имени:

import argparse

parser = argparse.ArgumentParser(description="Simple greeting script")
parser.add_argument("name", help="User name to greet")

args = parser.parse_args()
print(f"Hello, {args.name}!")


Запускаем из терминала:

python greet.py Alice
# Hello, Alice!


Попробуйте python greet.py -h — справка генерируется автоматически.

---

### Опциональные флаги и значения по умолчанию

Добавим флаг --uppercase и параметр --times:

import argparse

parser = argparse.ArgumentParser(description="Advanced greeting script")
parser.add_argument("name", help="User name to greet")
parser.add_argument(
"-t", "--times",
type=int,
default=1,
help="How many times to repeat greeting"
)
parser.add_argument(
"-u", "--uppercase",
action="store_true",
help="Print greeting in uppercase"
)

args = parser.parse_args()

greeting = f"Hello, {args.name}!"
if args.uppercase:
greeting = greeting.upper()

for _ in range(args.times):
print(greeting)


Примеры запуска:

python greet.py Bob -t 3
python greet.py Bob -t 2 -u


---

### Выбор из ограниченного набора значений

Частая задача — режим работы: debug, info, error. Используем choices:

import argparse

parser = argparse.ArgumentParser(description="Logging level demo")
parser.add_argument(
"--level",
choices=["debug", "info", "error"],
default="info",
help="Logging level"
)

args = parser.parse_args()
print(f"Selected level: {args.level}")


Если передать неправильное значение, argparse сам ругнется и покажет помощь.

---

### Что в итоге

argparse умеет:

- разбирать позиционные и опциональные аргументы;
- автоматически генерировать -h/--help;
- проверять типы (type=int, float, и т.д.);
- ограничивать значения (choices);
- удобно работать с флагами (action="store_true").

Освоив этот модуль, вы переводите свои скрипты из категории «сделал для себя» в категорию «это можно отдавать другим и не стыдиться».
👍1
- Работа с Google Sheets API для автоматизации работы с таблицами.
Python для начинающих: автоматизируем Google Sheets через API

Работа с Excel надоела, а таблицы в Google Sheets растут как грибы? Самое время подключить Python и заставить таблицы работать за вас.

### Что понадобится

1. Аккаунт Google.
2. Включить Google Sheets API и создать Service Account в Google Cloud Console.
3. Скачать JSON‑ключ сервисного аккаунта.
4. Выдать этому сервисному аккаунту доступ к нужной таблице (Share → по email из JSON).

Устанавливаем нужные пакеты:

pip install gspread google-auth


### Подключение к таблице

import gspread
from google.oauth2.service_account import Credentials

SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]
creds = Credentials.from_service_account_file(
"service_account.json",
scopes=SCOPES
)

client = gspread.authorize(creds)
sheet = client.open("Sales Report").sheet1 # первая вкладка


Теперь sheet — это объект рабочей таблицы, с которым можно делать почти всё.

### Чтение данных

Получим все строки и заголовок:

rows = sheet.get_all_records()  # список dict'ов
header = sheet.row_values(1) # первая строка
print(header)
print(rows[:3]) # первые три записи


Так удобно превращать таблицу в «мини-базу данных».

### Запись и обновление

Запишем заголовок и пару строк:

data_header = ["Date", "Product", "Quantity", "Price"]
sheet.update("A1:D1", [data_header])

new_rows = [
["2025-01-01", "Keyboard", 3, 59.9],
["2025-01-02", "Mouse", 5, 29.5],
]
sheet.append_rows(new_rows)


append_rows добавляет данные в конец, не нужно считать, какая строка следующая.

Обновим цену в конкретной ячейке:

sheet.update("D2", 79.9)


### Массовые обновления

Если нужно поменять сразу блок данных — используем диапазон:

discounted = [
["Keyboard", 49.9],
["Mouse", 24.9],
]
sheet.update("B2:C3", discounted)


### Небольшая автоматизация: перерасчёт итогов

Добавим в таблицу столбец с итоговой суммой:

values = sheet.get_all_values()
header = values[0]
rows = values[1:]

quantity_idx = header.index("Quantity")
price_idx = header.index("Price")

totals = []
for row in rows:
try:
qty = float(row[quantity_idx])
price = float(row[price_idx])
totals.append([qty * price])
except ValueError:
totals.append([""])

start_row = 2
end_row = start_row + len(totals) - 1
sheet.update(f"E{start_row}:E{end_row}", totals)
sheet.update("E1", "Total")


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

Google Sheets API + Python — это быстрый способ превратить обычную таблицу в часть автоматизированного пайплайна: собирать данные, очищать, пересчитывать и готовить отчеты без ручного копипаста.
🔥31
- Как работать с параллельными потоками данных с использованием Apache Kafka.
Как работать с параллельными потоками данных с Apache Kafka и Python

Представь себе конвейер в заводском цеху: по ленте бесконечно едут детали, а рабочие на разных станциях что‑то с ними делают. Apache Kafka — это примерно такой же конвейер, только для данных. Она позволяет принимать, хранить и отдавать миллионы сообщений в реальном времени. Python здесь может быть “рабочим”, который эти данные обрабатывает.

---

### Основные термины Kafka

- Broker — сервер Kafka, который хранит сообщения.
- Topic — “лента”, куда пишутся сообщения (например, user_events).
- Partition — кусок топика. Именно разделы позволяют обрабатывать сообщения параллельно.
- Producer — отправляет сообщения в Kafka.
- Consumer — читает сообщения из Kafka.
- Consumer group — группа потребителей, которые совместно читают один топик, автоматически деля партиции между собой.

Чем больше партиций у топика и чем больше потребителей в группе, тем выше параллелизм.

---

### Установка клиента для Python

Один из популярных клиентов — confluent-kafka (тонкая обертка над C-библиотекой):

pip install confluent-kafka


---

### Простой producer: отправляем события

from confluent_kafka import Producer
import json

producer = Producer({"bootstrap.servers": "localhost:9092"})

def delivery_report(err, msg):
if err is not None:
print(f"Delivery failed: {err}")
else:
print(f"Delivered to {msg.topic()} [{msg.partition()}] at offset {msg.offset()}")

for user_id in range(1, 6):
event = {"user_id": user_id, "action": "click"}
producer.produce(
topic="user_events",
value=json.dumps(event).encode("utf-8"),
callback=delivery_report
)

producer.flush()


Сообщения попадают в топик user_events. Kafka сама распределяет их по партициям (по умолчанию — по хешу ключа, если он есть).

---

### Параллельное чтение: несколько consumers в одной группе

Ключ к параллельности — использовать одну consumer group и задать топику несколько партиций (например, 3). Тогда, если ты запустишь этот скрипт в нескольких процессах, Kafka раздаст им партиции автоматически.

from confluent_kafka import Consumer, KafkaException
import json

consumer = Consumer({
"bootstrap.servers": "localhost:9092",
"group.id": "analytics_group",
"auto.offset.reset": "earliest",
})

consumer.subscribe(["user_events"])

try:
while True:
msg = consumer.poll(1.0)
if msg is None:
continue
if msg.error():
raise KafkaException(msg.error())
event = json.loads(msg.value().decode("utf-8"))
print(
f"Process: handled user={event['user_id']} "
f"from partition={msg.partition()} offset={msg.offset()}"
)
finally:
consumer.close()


Теперь магия:
- Увеличиваешь количество процессов/контейнеров с этим consumer’ом — обработка масштабируется.
- Kafka сама следит, кто какие партиции читает, и перераспределяет их при падении одного из экземпляров.

---

### Практические советы

1. Думай о ключах сообщений: одинаковый ключ → одинаковая партиция → удобно гарантировать порядок для конкретного пользователя.
2. Используй consumer groups для разных задач: аналитика, логирование, алерты могут читать один и тот же топик независимо.
3. Следи за offset’ами: по умолчанию Kafka фиксирует прогресс чтения, чтобы после рестартов не терять сообщения.

Kafka + Python позволяют строить конвейеры обработки данных, которые легко масштабируются горизонтально. Для начинающего питониста это хороший шаг от “скриптиков” к полноценным потоковым системам.
👍1
- Основы работы с мемкэшем и Redis для кэширования данных.