Работа с аудиофайлами: основное введение в модуль wave
Представьте, что вы хотите прочитать или обработать аудиофайл формата WAV в Python. Где-то на жестком диске томно покоится классическая мелодия “Moonlight.wav”, и вашей задачей становится: узнать её параметры или скопировать пару секунд звука в новый файл. Как это сделать? Представляю простое, но очень полезное оружие из стандартной библиотеки — модуль wave.
### В чём суть формата WAV?
WAV — это контейнер для хранения необработанных (raw) аудиоданных, обычно с минимальным сжатием. Как правило, это PCM-звук: каждая секунда — это тысячи отсчётов-чисел, определяющих амплитуду сигнала.
### Простое чтение WAV-файла
Модуль wave позволяет безопасно заглянуть внутрь файла и считать метаданные: количество каналов, частоту дискретизации и длину.
Всё, что между
### Извлечение и сохранение кусочка аудио
Допустим, нужно вырезать первые 5 секунд аудио и записать их в новый WAV файл.
Модуль wave работает только с несжатым PCM-звуком, но зато позволяет управлять WAV-файлами без лишних зависимостей.
### Секреты и ограничения модуля wave
wave — это абсолютный минималист. Он не умеет работать с mp3/flac и не воспроизводит звук. Но если хочется быстро проанализировать структуру WAV или сделать простейшее редактирование, — это именно ваш инструмент.
Используйте wave, если вам нужно: узнать, как устроена “под капотом” музыка, или написать свою первую аудиопрограмму на Python!
Представьте, что вы хотите прочитать или обработать аудиофайл формата 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 для начинающих: как приручить
Когда скрипт разрастается до 500+ строк, появляется соблазн «просто дописать еще чуть-чуть». А потом — боль: сложно найти нужную функцию, тестировать, переиспользовать код. Время знакомиться с модульной структурой и файлом
---
### Что такое пакет и зачем нужен
Пакет — это просто папка с Python-кодом, которую интерпретатор воспринимает как модуль. Классический пакет содержит:
Наличие
---
### Простейший пример: группируем логику
Пусть у нас мини-приложение для работы с пользователями.
Теперь сделаем пакет удобным с помощью
Теперь в основном скрипте:
Мы спрятали внутреннюю структуру (файлы
---
### Вложенные пакеты и точечный импорт
Добавим утилиты:
И обновим
Теперь в любом месте проекта:
---
### Зачем вообще заморачиваться с
1. Чистый публичный API
Через
2. Сокрытие структуры
Можно переименовать файл
3. Удобные групповые импорты
Вместо:
достаточно:
4. Инициализация пакета
В
---
### Маленькое правило напоследок
Если модулей становится слишком много, и
__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__.py1. Чистый публичный 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
Иногда хочется почувствовать себя чуть ближе к «низам» интернета — туда, где нет Flask и Django, а есть только чистые сокеты и байты. Давайте напишем свой минимальный TCP‑сервер и разберёмся, что вообще происходит «под капотом».
### Что такое сокет?
Сокет — это конечная точка сетевого соединения. У простого TCP-сервера есть три основных шага:
1. Создать сокет.
2. Привязать его к адресу и порту.
3. Слушать входящие подключения и обрабатывать клиентов.
Используем стандартный модуль
### Самый простой TCP‑сервер
Напишем сервер, который принимает соединение и отсылает клиенту приветствие:
Кратко по шагам:
-
-
-
-
-
Проверить можно через
### Эхо‑сервер: отвечаем на сообщения
Сделаем сервер, который читает данные от клиента и отправляет их обратно:
Здесь важно:
-
-
- цикл
### О чём стоит помнить
- Порт должен быть свободен, иначе будет ошибка
- При разработке удобно использовать
- Такой сервер однопоточен: пока он общается с одним клиентом, другие ждут. Для реальных задач нужны потоки (
Через такие простые примеры становится понятнее, что веб‑фреймворки всего лишь надстройка над таким же
Иногда хочется почувствовать себя чуть ближе к «низам» интернета — туда, где нет 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-проекта: CI за 10 минут
Ты пишешь код, пушишь его в репозиторий… и только потом вспоминаешь, что не запустил тесты. Классика. GitHub Actions решает эту проблему: он запускает проверки автоматически при каждом коммите или pull request.
Разберём минимальный, но полезный воркфлоу для Python.
---
### Шаг 1. Структура проекта
Допустим, у тебя такой проект:
---
### Шаг 2. Пишем простой код и тест
Добавь
---
### Шаг 3. Создаём воркфлоу GitHub Actions
В репозитории создай папку
Что тут происходит:
-
-
-
-
-
-
---
### Шаг 4. Бонус: проверка стиля
Добавим линтер
И ещё один шаг в воркфлоу:
Теперь каждый коммит проходит:
1. Установку зависимостей
2. Линтер
3. Тесты на нескольких версиях Python
Если что-то падает — GitHub подсветит это прямо в Pull Request.
---
GitHub Actions превращает твой репозиторий в маленький конвейер качества: ты пишешь код — он сам проверяет, что ты ничего не сломал. Настроить один раз — экономить часы и нервы постоянно.
Ты пишешь код, пушишь его в репозиторий… и только потом вспоминаешь, что не запустил тесты. Классика. 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 — это как карандаш для программиста: без него работать можно, но рисовать данные неудобно. Библиотека умеет строить почти любые графики, а начинать лучше с простого: линейных, точечных и столбчатых диаграмм.
---
### Первый график за 5 строк
Установите библиотеку (если нужно):
Базовый пример:
---
### Цвета, маркеры и стили линий
Matplotlib позволяет легко “приодеть” график:
Что полезно запомнить:
-
-
-
-
---
### Точечные и столбчатые графики
Для разброса точек используйте
Параметры:
Столбчатая диаграмма:
---
### Быстрая смена стиля оформления
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-инструментПочти каждый полезный скрипт рано или поздно превращается в маленькую консольную утилиту: нужно передать путь к файлу, режим работы, уровень логирования. Пихать всё в
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
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).
Устанавливаем нужные пакеты:
### Подключение к таблице
Теперь
### Чтение данных
Получим все строки и заголовок:
Так удобно превращать таблицу в «мини-базу данных».
### Запись и обновление
Запишем заголовок и пару строк:
Обновим цену в конкретной ячейке:
### Массовые обновления
Если нужно поменять сразу блок данных — используем диапазон:
### Небольшая автоматизация: перерасчёт итогов
Добавим в таблицу столбец с итоговой суммой:
Теперь таблица сама считает сумму по строке, а вы можете раз в день запускать скрипт и обновлять отчеты.
Google Sheets API + Python — это быстрый способ превратить обычную таблицу в часть автоматизированного пайплайна: собирать данные, очищать, пересчитывать и готовить отчеты без ручного копипаста.
Работа с 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 — это быстрый способ превратить обычную таблицу в часть автоматизированного пайплайна: собирать данные, очищать, пересчитывать и готовить отчеты без ручного копипаста.
🔥3❤1
Как работать с параллельными потоками данных с Apache Kafka и Python
Представь себе конвейер в заводском цеху: по ленте бесконечно едут детали, а рабочие на разных станциях что‑то с ними делают. Apache Kafka — это примерно такой же конвейер, только для данных. Она позволяет принимать, хранить и отдавать миллионы сообщений в реальном времени. Python здесь может быть “рабочим”, который эти данные обрабатывает.
---
### Основные термины Kafka
- Broker — сервер Kafka, который хранит сообщения.
- Topic — “лента”, куда пишутся сообщения (например,
- Partition — кусок топика. Именно разделы позволяют обрабатывать сообщения параллельно.
- Producer — отправляет сообщения в Kafka.
- Consumer — читает сообщения из Kafka.
- Consumer group — группа потребителей, которые совместно читают один топик, автоматически деля партиции между собой.
Чем больше партиций у топика и чем больше потребителей в группе, тем выше параллелизм.
---
### Установка клиента для Python
Один из популярных клиентов —
---
### Простой producer: отправляем события
Сообщения попадают в топик
---
### Параллельное чтение: несколько consumers в одной группе
Ключ к параллельности — использовать одну consumer group и задать топику несколько партиций (например,
Теперь магия:
- Увеличиваешь количество процессов/контейнеров с этим consumer’ом — обработка масштабируется.
- Kafka сама следит, кто какие партиции читает, и перераспределяет их при падении одного из экземпляров.
---
### Практические советы
1. Думай о ключах сообщений: одинаковый ключ → одинаковая партиция → удобно гарантировать порядок для конкретного пользователя.
2. Используй consumer groups для разных задач: аналитика, логирование, алерты могут читать один и тот же топик независимо.
3. Следи за offset’ами: по умолчанию Kafka фиксирует прогресс чтения, чтобы после рестартов не терять сообщения.
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
Основы работы с Memcached и Redis для кэширования данных
Если ваш Python‑код постоянно лезет в базу за одними и теми же данными — вы жжёте процессор и тормозите приложение. В таких случаях на сцену выходят Memcached и Redis — быстрые in‑memory хранилища, идеальные для кэширования.
---
### Зачем нужен кэш
Кэширование — это сохранение заранее вычисленных результатов в память, чтобы не пересчитывать и не запрашивать их повторно. Типичный сценарий:
1. Проверяем кэш.
2. Если данных нет — обращаемся к БД / API.
3. Кладём результат в кэш.
4. В следующий раз берём из кэша за миллисекунды.
---
### Memcached: минималистичный и быстрый
Memcached — это просто распределённый словарь в памяти: ключ–значение, без сложных типов данных.
Установка клиента:
Пример:
Особенности Memcached:
- Нет персистентности: перезапустили — всё забыто.
- Простые типы (строки/байты).
- Идеален как быстрый временный кэш поверх БД.
---
### Redis: швейцарский нож кэширования
Redis умеет больше: строки, списки, множества, хэши, TTL, pub/sub, транзакции и персистентность.
Установка:
Пример кэша с TTL:
Пример использования сложных структур: счётчик просмотров товара:
---
### Что выбрать новичку
- Memcached, если нужен простой, сверхбыстрый кэш без сложных структур и персистентности.
- Redis, если хотите кэш + дополнительные возможности (счётчики, очереди, сессии, персистентность).
Для учебных проектов Redis часто удобнее: он универсален и его легче масштабировать по мере усложнения системы.
Если ваш Python‑код постоянно лезет в базу за одними и теми же данными — вы жжёте процессор и тормозите приложение. В таких случаях на сцену выходят Memcached и Redis — быстрые in‑memory хранилища, идеальные для кэширования.
---
### Зачем нужен кэш
Кэширование — это сохранение заранее вычисленных результатов в память, чтобы не пересчитывать и не запрашивать их повторно. Типичный сценарий:
1. Проверяем кэш.
2. Если данных нет — обращаемся к БД / API.
3. Кладём результат в кэш.
4. В следующий раз берём из кэша за миллисекунды.
---
### Memcached: минималистичный и быстрый
Memcached — это просто распределённый словарь в памяти: ключ–значение, без сложных типов данных.
Установка клиента:
pip install pymemcache
Пример:
from pymemcache.client import base
client = base.Client(("localhost", 11211))
def get_user_profile(user_id: int) -> dict:
cache_key = f"user:{user_id}"
cached = client.get(cache_key)
if cached:
# данные хранятся как bytes; в реальном коде — json.loads(...)
print("from cache")
return eval(cached.decode("utf-8"))
print("from db")
user = {"id": user_id, "name": "Alice"} # тут должна быть реальная БД
client.set(cache_key, str(user).encode("utf-8"), expire=60)
return user
get_user_profile(1)
get_user_profile(1)
Особенности Memcached:
- Нет персистентности: перезапустили — всё забыто.
- Простые типы (строки/байты).
- Идеален как быстрый временный кэш поверх БД.
---
### Redis: швейцарский нож кэширования
Redis умеет больше: строки, списки, множества, хэши, TTL, pub/sub, транзакции и персистентность.
Установка:
pip install redis
Пример кэша с TTL:
import json
from redis import Redis
redis_client = Redis(host="localhost", port=6379, db=0)
def get_product(product_id: int) -> dict:
cache_key = f"product:{product_id}"
cached = redis_client.get(cache_key)
if cached:
print("from cache")
return json.loads(cached)
print("from db")
product = {"id": product_id, "title": "Keyboard", "price": 99.9}
redis_client.set(cache_key, json.dumps(product), ex=120)
return product
get_product(10)
get_product(10)
Пример использования сложных структур: счётчик просмотров товара:
def increment_views(product_id: int) -> int:
key = f"product:{product_id}:views"
return redis_client.incr(key)
print(increment_views(10))
print(increment_views(10))
---
### Что выбрать новичку
- Memcached, если нужен простой, сверхбыстрый кэш без сложных структур и персистентности.
- Redis, если хотите кэш + дополнительные возможности (счётчики, очереди, сессии, персистентность).
Для учебных проектов Redis часто удобнее: он универсален и его легче масштабировать по мере усложнения системы.
👍2
Использование pandas для преобразования и очистки данных
Если вы хоть раз открывали «сырой» CSV-файл, то знаете: данные редко бывают аккуратными. Пропуски, дубли, странные форматы дат — всё это мешает анализу. Здесь на сцену выходит
---
### Загрузка и первый взгляд на данные
Начнём с простого: прочитаем CSV и посмотрим, что внутри.
---
### Преобразование типов и работа с датами
Частая проблема — строки там, где должны быть числа или даты.
Параметр
---
### Очистка пропусков и дубликатов
Пропуски можно либо удалить, либо заполнить осмысленными значениями.
Для числовых столбцов часто используют среднее, медиану или 0 — зависит от задачи:
---
### Создание новых признаков
Pandas позволяет легко добавлять столбцы, основанные на уже существующих.
За пару строк кода можно превратить «сырые» данные в удобный набор признаков для анализа или модели.
---
### Фильтрация и группировка
Комбинация фильтрации и группировки — основа исследовательского анализа.
С помощью
---
Если вы хоть раз открывали «сырой» CSV-файл, то знаете: данные редко бывают аккуратными. Пропуски, дубли, странные форматы дат — всё это мешает анализу. Здесь на сцену выходит
pandas — швейцарский нож для работы с табличными данными в Python.---
### Загрузка и первый взгляд на данные
Начнём с простого: прочитаем CSV и посмотрим, что внутри.
import pandas as pd
df = pd.read_csv("sales.csv")
print(df.head())
print(df.info())
head() показывает первые строки, info() — типы столбцов и наличие пропусков. Уже отсюда часто можно понять, где бардак: например, даты хранятся как object, а суммы — как строки.---
### Преобразование типов и работа с датами
Частая проблема — строки там, где должны быть числа или даты.
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df["date"] = pd.to_datetime(df["date"], errors="coerce")
Параметр
errors="coerce" превращает невозможные значения в NaN. Это удобно: дальше их можно явно обработать, а не ловить таинственные ошибки.---
### Очистка пропусков и дубликатов
Пропуски можно либо удалить, либо заполнить осмысленными значениями.
# Удаляем строки, где нет суммы покупки
df = df.dropna(subset=["amount"])
# Заполняем пропущенный город значением "Unknown"
df["city"] = df["city"].fillna("Unknown")
# Удаляем полные дубликаты строк
df = df.drop_duplicates()
Для числовых столбцов часто используют среднее, медиану или 0 — зависит от задачи:
df["discount"] = df["discount"].fillna(df["discount"].median())
---
### Создание новых признаков
Pandas позволяет легко добавлять столбцы, основанные на уже существующих.
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["amount_with_tax"] = df["amount"] * 1.2
За пару строк кода можно превратить «сырые» данные в удобный набор признаков для анализа или модели.
---
### Фильтрация и группировка
Комбинация фильтрации и группировки — основа исследовательского анализа.
# Оставим только заказы после 2023 года и с положительной суммой
filtered = df[(df["date"].dt.year >= 2023) & (df["amount"] > 0)]
# Посчитаем суммарные продажи по городам
city_stats = (
filtered
.groupby("city", as_index=False)["amount"]
.sum()
.rename(columns={"amount": "total_amount"})
)
print(city_stats.head())
С помощью
groupby и агрегирующих функций (sum, mean, count и др.) можно быстро получать сводки и отчёты, не трогая Excel.---
pandas превращает хаотичный CSV в аккуратный, структурированный датафрейм, с которым приятно работать. Чем раньше вы начнёте его использовать, тем меньше времени будете тратить на рутину и тем больше — на сам анализ.👍1