Python для начинающих
1.06K subscribers
280 photos
3 videos
232 files
61 links
Python для начинающих
Download Telegram
Создание и использование ORM для взаимодействия с базами данных.
Привет! Сегодня мы окунемся в мир ORM — Object-Relational Mapping. Звучит как заклинание, да? На деле, всё проще: ORM позволяет работать с базой данных, как будто вы работаете с обычными объектами Python. Больше никаких SQL-запросов, только чистый, приятный код. Давайте разберемся, как это работает и чем нам это может помочь.

Представьте, вы пишете блог (как я!) и хотите хранить информацию о статьях: заголовок, текст, дату публикации. Можно, конечно, вручную конструировать SQL-запросы, трекать подключения к базе, писать конвертацию типов. А можно — просто использовать ORM, например, SQLAlchemy или Peewee.

Начнем с SQLAlchemy — одного из самых популярных вариантов.

Устанавливаем:

pip install sqlalchemy


Создадим простое приложение:

from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime

Base = declarative_base()

class Post(Base):
__tablename__ = 'posts'

id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
published_at = Column(DateTime, default=datetime.utcnow)

# Настраиваем соединение с SQLite
engine = create_engine('sqlite:///blog.db')
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

# Создаем и сохраняем пост
new_post = Post(title="My First ORM Post", content="ORMs make life easier!")
session.add(new_post)
session.commit()


Готово! Мы только что:

- Создали таблицу в SQLite без единого SQL-запроса
- Вставили новую запись в базу данных
- Использовали объектно-ориентированный подход

Если вы знакомы с Django, то знаете, что у него свой встроенный ORM — возможно, один из лучших для быстрого старта. Но если вы хотите легковесность и контроль — SQLAlchemy и Peewee (более минималистичный вариант) вас приятно удивят.

Для сравнения — как выглядит чтение данных:

posts = session.query(Post).filter(Post.title.like("%ORM%")).all()
for post in posts:
print(post.title, post.published_at)


Или обновление:

post = session.query(Post).first()
post.title = "Updated title"
session.commit()


Да, ORM не избавляет от необходимости думать о данных, транзакциях и индексации. Но он делает код чище, безопаснее и легче в сопровождении.

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

В следующий раз расскажу, как связать несколько таблиц и делать отношения "один-ко-многим" в ORM-стиле. А пока — протестируйте код выше, поэкспериментируйте. Ведь лучший способ выучить ORM — начать его действительно использовать!
👍1
Как асинхронное программирование улучшает производительность сетевых приложений.
🔥 Как асинхронное программирование улучшает производительность сетевых приложений?

Если вы уже писали на Python сетевые приложения — например, телеграм-бота, простенький HTTP-сервер или парсер сайтов — вы, скорее всего, сталкивались с тем, что программа "зависает", когда ждет ответа от сервера. В этот момент Python… просто сидит и ждет. Чай себе заваривает. А вы — греете процессор на холостом ходу.

Но можно по-другому. Асинхронно. И вот в тот момент, когда вы впервые запускаете свой async-код и видите, как он в разы быстрее перебирает запросы, возникает ощущение магии. На самом деле, никакой магии — просто асинхронность.

🧠 Что происходит в обычной программе?

Вот пример кода, написанного "по старинке":

import requests

def fetch_data():
response = requests.get('https://httpbin.org/delay/2')
return response.text

for _ in range(5):
print(fetch_data())


Каждый запрос “зависает” на 2 секунды (сайт задерживает выдачу ответа). Всего уходит около 10 секунд. Никакой многозадачности — каждая следующая итерация ждет завершения предыдущей.

📈 А теперь асинхронный подход:

import asyncio
import aiohttp

async def fetch(session, url):
async with session.get(url) as response:
return await response.text()

async def main():
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, 'https://httpbin.org/delay/2') for _ in range(5)]
results = await asyncio.gather(*tasks)
for r in results:
print(r)

asyncio.run(main())


Вся пятерка запросов отрабатывает… параллельно! aiohttp и asyncio позволяют не простаивать в ожидании ответа, а запускать другие задачи.

Результат? Вместо 10 секунд — примерно 2 секунды. Гениально просто.

⚙️ Почему это работает?

Асинхронная модель основана на событийном цикле. Когда вы делаете операцию ввода-вывода — например, ждете данные из интернета — интерпретатор Python освобождает поток и занимается другими задачами. Этот подход отлично работает, когда операций ввода-вывода много, а процессор почти не загружен — типичная ситуация для сетевых приложений.

Монолитный requests и другие синхронные библиотеки всегда блокируют выполнение, пока не получат результат. Async дает экономию времени, когда у вас десятки, сотни запросов, и каждый из них можно запускать одновременно.

💥 Где использовать асинхронность?

- Боты и чат-приложения (async-сервер получает и отправляет сообщения без задержек)
- Web API-клиенты (одновременно дергаем десятки API)
- Парсеры сайтов (асинхронный скачиватель страниц)
- Веб-серверы (FastAPI и aiohttp прекрасно работают в async-режиме)

☝️ Важно понимать: асинхронность — это не многопоточность. Она не ускорит вашу математику или генерацию изображений. Но она незаменима там, где приложение тратит время на ожидание.

🎯 Вывод

Асинхронное программирование в Python — это не роскошь, а инструмент оптимизации. Особенно в сетевых задачах, где каждый миллисекундный выигрыш ускоряет приложение многократно.

Python дает вам отличные async-инструменты прямо из коробки: asyncio, aiohttp, FastAPI, httpx и другие. Освоив их однажды, вы больше никогда не захотите возвращаться к бесконечным “зависаниям”.
🔥1
Разработка приложений для анализа и визуализации данных с использованием Plotly Dash.
Если тебе когда-нибудь хотелось создать веб-приложение для анализа данных — и при этом не хочется влезать в мир JavaScript, HTML и CSS — то ты попал по адресу. Сегодня я расскажу про Plotly Dash: мощный инструмент для построения интерактивных аналитических приложений, полностью на Python. Звучит как магия? Это потому, что почти так и есть.

Plotly Dash — это библиотека на Python, которая позволяет создавать веб-приложения для визуализации и анализа данных с помощью кода, который выглядит как обычный скрипт. Без необходимости знать фронтенд. Интерфейс строится на основе компонент React, но всё спрятано под капотом — ты просто создаёшь layout и указываешь логику в виде Python-функций.

Рассмотрим простейший пример.

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

pip install dash


Теперь код приложения:

import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import numpy as np
import plotly.graph_objs as go

app = dash.Dash(__name__)

app.layout = html.Div([
html.H1("Dynamic Sine Wave Plot"),
dcc.Slider(
id='frequency-slider',
min=1,
max=10,
step=0.5,
value=1,
marks={i: str(i) for i in range(1, 11)}
),
dcc.Graph(id='sine-graph')
])

@app.callback(
Output('sine-graph', 'figure'),
Input('frequency-slider', 'value')
)
def update_graph(frequency):
x_vals = np.linspace(0, 2 * np.pi, 500)
y_vals = np.sin(frequency * x_vals)
figure = go.Figure(
data=[
go.Scatter(x=x_vals, y=y_vals, mode='lines', name='Sine Wave')
],
layout=go.Layout(
title=f"Sine Wave with Frequency {frequency}",
xaxis={'title': 'x'},
yaxis={'title': 'sin(f*x)'}
)
)
return figure

if __name__ == '__main__':
app.run_server(debug=True)


Это полноценное веб-приложение. На странице пользователь может регулировать ползунок, меняющий частоту синусоиды, и график будет обновляться в реальном времени. Всё это — с минимальным количеством кода.

Dash особенно мощен, когда тебе нужно построить интерактивные фильтры данных, таблицы, выпадающие списки, вкладки, загрузку CSV-файлов — для всего этого уже есть готовые компоненты. Соединение Plotly (интерактивные графики) и Dash (веб-интерфейс плюс логика) делает библиотеку отличным выбором для Data Science.

Дополнительно Dash легко разворачивается на Heroku, Render или любой другой платформе с поддержкой Python. А значит, ты можешь делать прототипы, MVP и небольшие демонстрационные проекты без громоздких фреймворков.

Совет от меня: начни с чего-то простого. Например, загрузка CSV-файла и построение графика по выбранным колонкам. Это поможет понять принципы связи layout-компонентов и callback-функций. А дальше — хоть предиктивная аналитика с машинным обучением!

Dash не заменит тебе полноценную веб-разработку, но если ты Python-разработчик, которому нужно быстро визуализировать данные — это просто находка.
1🔥1
Создание и настройка сред тестирования для Python проектов.
🔍 Создание и настройка сред тестирования для Python проектов

Если вы только начинаете путешествие по миру Python, рано или поздно столкнётесь с необходимостью тестировать свой код. И вот тут начинается магия: автоматические тесты, виртуальные окружения, покрытие кода — всё это становится неотъемлемой частью любого серьёзного проекта. Сегодня разберём, как создать и настроить удобную и гибкую среду тестирования, с которой приятно работать.

🎯 Начнем с основ: виртуальное окружение

Работаем только в virtual environment. Это спасёт вас от конфликтов зависимостей и превращения системы в «зоопарк» библиотек.

Создаём окружение:

python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate


Теперь все зависимости будут установлены локально. Отлично!

🧪 Подключаем pytest

Для начала работы с тестами советую использовать pytest. Он лаконичен, мощен и популярен в сообществе. Установим его:

pip install pytest


Создайте файл с тестами test_math_utils.py:

def add(a, b):
return a + b

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

def test_add_negative_numbers():
assert add(-1, -1) == -2


Запуск всех тестов:

pytest


🔥 Бонус: автопоиск файлов с тестами, читаемые отчёты и подсветка ошибок прямо в терминале!

📦 Организация структуры проекта

Хорошая структура проекта помогает тестированию:

my_project/

├── src/
│ └── core.py
├── tests/
│ └── test_core.py
├── requirements.txt
└── pytest.ini


В pytest.ini можно настраивать поведение pytest:

[pytest]
testpaths = tests
python_files = test_*.py


📈 Настройка покрытия кода

Хотите знать, сколько строк вашего кода реально покрыто тестами? Добавьте pytest-cov:

pip install pytest-cov
pytest --cov=src tests/


Результат вас удивит: будет показано, какие строки были выполнены, а какие – нет. Это незаменимо для отслеживания «мертвого» кода.

🔧 Прогон тестов перед коммитом

Используйте pre-commit hooks, чтобы тесты автоматически запускались перед отправкой коммитов. Добавим файл .pre-commit-config.yaml:

repos:
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.3.2
hooks:
- id: prettier
- repo: https://github.com/pre-commit/mirrors-pylint
rev: v2.13.9
hooks:
- id: pylint
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: v1.6.0
hooks:
- id: autopep8


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

pip install pre-commit
pre-commit install


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

📚 Резюмируем

- Используйте venv для изоляции сред
- pytest – ваш друг в мире тестов
- Настройте pytest.ini под структуру проекта
- Подключайте pytest-cov для анализа покрытия
- Используйте pre-commit для автоматизации проверок

Грамотно выстроенная среда тестирования экономит часы отладки, делает проект масштабируемым и увеличивает ваше доверие к собственному коду. Успехов! 🚀
Как создавать сценарии и оцифровки для интерактивных фильмов на Python.
Название: Сценарий оживает — пишем интерактивные фильмы на Python

Интерактивное кино — это где пользователь чувствует себя режиссёром. Помните Black Mirror: Bandersnatch? Или игры от Telltale? Хочешь такого же эффекта, но на Python? Легко.

В этом посте я расскажу, как создавать интерактивные сценарии, с поддержкой переходов, ветвлений и даже "оцифровки" сюжета — структуру, по которой можно визуализировать сюжет как дерево.

Ключевая идея — представить сценарий в виде графа, где каждая сцена — это узел, а выбор — это ребро. Для начала создадим структуру сцены.

📦 Основной ингредиент: простая модель сцены

class Scene:
def __init__(self, text, choices):
self.text = text
self.choices = choices # {'choice_text': next_scene_key}


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

story = {
"start": Scene(
"Ты просыпаешься в лесу. На севере слышны шаги. На юге видишь свет костра.",
{
"Пойти на север": "north_path",
"Пойти на юг": "campfire"
}
),
"north_path": Scene(
"Ты натыкаешься на странного мужчину с топором.",
{
"Поздороваться": "talk_man",
"Спрятаться": "hide"
}
),
"campfire": Scene(
"Около костра сидят путешественники. Они машут тебе рукой.",
{
"Присоединиться": "join_travelers",
"Убежать в лес": "run_away"
}
),
# ...
}


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

def play(story, start_key):
current_key = start_key
while current_key in story:
scene = story[current_key]
print(f"\n{scene.text}\n")
for i, choice in enumerate(scene.choices.keys(), 1):
print(f"{i}. {choice}")
try:
index = int(input("Выбери действие: ")) - 1
choice_text = list(scene.choices.keys())[index]
current_key = scene.choices[choice_text]
except (IndexError, ValueError):
print("Неверный выбор. Попробуй снова.")


И запускаем:

if __name__ == "__main__":
play(story, "start")


📊 Теперь — оцифровка: дерево выбора

Допустим, ты хочешь отрисовать структуру сюжета. Здесь пригодится модуль graphviz.

Установим его:

pip install graphviz


Теперь можно визуализировать сюжет:

from graphviz import Digraph

def export_story_graph(story, filename="story"):
dot = Digraph()
for key, scene in story.items():
dot.node(key, scene.text[:30] + ("..." if len(scene.text) > 30 else ""))
for choice_text, next_key in scene.choices.items():
dot.edge(key, next_key, label=choice_text)
dot.render(filename, format='png', cleanup=True)

export_story_graph(story)


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

🧩 Идеи для расширения:

- Добавить условные переходы в зависимости от состояния игрока (что он уже выбрал ранее).
- Сохранять прохождения.
- Автоматическая генерация HTML/Web-интерфейса.
- Генерация сценария из JSON или YAML — удобно авторам без знаний Python.

🎬 Вывод

На Python легко создать интерактивную историю, точнее — движок для неё. Но самый главный ингредиент — твоя фантазия. Python в этом случае — режиссёрская панель и монтажный отсек одновременно. Такое кино ты нигде не купишь — ты его пишешь сам.
Оптимизация процессов разработки с использованием Makefile и Python.
Python и Makefile: друзья или соседи, которые делают вид, что не знакомы? Большинство начинающих разработчиков вообще не знают, что у них под носом скрыт весьма могущественный инструмент автоматизации — Makefile. Если вы всё ещё вручную запускаете тесты, линтеры, форматтеры, и каждый раз вспоминаете, какой командой деплоится скрипт — пора знакомиться с make.

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

Давайте рассмотрим, как можно организовать простой Makefile под типичный проект на Python.

Предположим, у нас в проекте есть следующая структура:

my_project/
├── src/
│ └── main.py
├── tests/
│ └── test_main.py
├── requirements.txt
├── Makefile


Вот базовый вариант Makefile, который выполняет часто повторяющиеся задачи:

.PHONY: install test lint format run

install:
pip install -r requirements.txt

test:
pytest tests/

lint:
flake8 src/ tests/

format:
black src/ tests/

run:
python src/main.py


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

- install — установка зависимостей проекта.
- test — запуск ваших тестов, например, с помощью pytest.
- lint — проверка стиля кода с помощью flake8.
- format — автоматическое форматирование при помощи black.
- run — запуск основного скрипта проекта.

Допустим, вы хотите быстро проверить код перед коммитом. Одной командой вы можете прогнать форматтер, линтер и тесты:

make format lint test


А если проект сложнее? Например, у вас разные настройки для dev и prod окружений. Тогда Makefile спасает и здесь:

run-dev:
ENV=development python src/main.py

run-prod:
ENV=production python src/main.py


Или хотите максимально упростить работу в команде? Добавьте цель init:

init: install format lint test


Теперь новому участнику команды достаточно одной команды make init, и он получит всё необходимое для старта.

Особенность Makefile в его декларативности. Вы просто пишете, что хотите сделать, а make разруливает зависимости и порядок выполнения. Даже если вы профи в bash-скриптах, Makefile удобно читается и отлично документирует процессы.

В завершение — если вы думаете, что Makefile — это только для бэкенда или devops-разработчиков, вы удивитесь, как хорошо он встраивается даже в ML-проекты, автоматизируя запуск моделей, сбор данных, преобразования и т.д.

Автоматизация = скорость + надежность. С Makefile вы тратите меньше времени на рутину, и больше — на собственно код. А Python и Makefile — невероятно гармоничная пара, когда нужно наладить процесс, но не хочется городить сложные системы сборки.
Проектирование высоконагруженных систем на базе Python.
Проектирование высоконагруженных систем на базе Python: мифы и реальность

Когда речь заходит о высоконагруженных системах, Python обычно воспринимается с опаской. “Медленный”, “интерпретируемый”, “не подходит для продакшена” — и это лишь малая часть мифов. Но на деле — Python способен справляться с серьёзными нагрузками, если использовать его правильно. Давайте разберёмся, на что он действительно способен и какие инструменты пригодятся.

🐍 Лёгкие, но мощные: FastAPI и Uvicorn

Для создания высокопроизводительного backend-сервиса важно выбрать правильный веб-фреймворк. Flask — хорош, но для серьёзных задач лучше использовать FastAPI. Он построен на Starlette и использует типизацию, что упрощает отладку и повышает читаемость кода.

Пример минимального, но асинхронного API:

from fastapi import FastAPI

app = FastAPI()

@app.get("/ping")
async def ping():
return {"message": "pong"}


Запуск через Uvicorn:

uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4


Uvicorn — это ASGI-сервер, который обрабатывает запросы асинхронно и масштабируется за счёт запуска нескольких воркеров.

⚙️ Асинхронность = масштабируемость

Python не любит многопоточность из-за GIL (Global Interpreter Lock), но с асинхронным кодом справляется отлично. Используйте asyncio, чтобы обрабатывать тысячи соединений одновременно, например, когда пишите WebSocket-сервер или микросервис, который часто обращается к внешним API.

Пример с aiohttp:

import aiohttp
import asyncio

async def fetch(session, url):
async with session.get(url) as response:
return await response.text()

async def main():
async with aiohttp.ClientSession() as session:
html = await fetch(session, 'https://example.com')
print(html)

asyncio.run(main())


🧵 Background-задачи и воркеры: Celery, RQ

Если ваш сервис выполняет тяжёлые задачи (например, генерация отчёта или отправка email), лучше выносить их из основного потока. Для этого используют Celery или RQ. Эти библиотеки работают с очередями (Redis, RabbitMQ) и позволяют обрабатывать задачи в фоне.

Пример задачи на Celery:

from celery import Celery

app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def add(a, b):
return a + b


Основной сервис отдаёт задачу в очередь, рабочие процессы Celery её исполняют — и ваш API не блокируется.

📦 Кэш как спасение: Redis и Memcached

Часто повторяющиеся вычисления можно кэшировать. Например, если запрос к БД занимает 300 мс, а вы получаете одинаковые данные каждую минуту — кэш устранит задержку. Варианты:

- Redis (популярный, кроссплатформенный, даёт TTL, pub/sub и даже persistent-режим)
- Memcached (чуть быстрее по памяти, но без поддержки сложных типов данных)

Пример с redis-py:

import redis

cache = redis.Redis(host='localhost', port=6379, db=0)

def get_data():
cached = cache.get("key")
if cached:
return cached
# expensive operation
result = "expensive_result"
cache.setex("key", 60, result)
return result


🧠 Мониторинг и профилирование

Знать узкие места в коде — половина успеха.
Используйте:

- cProfile для анализа производительности
- prometheus_client для метрик
- Grafana + Prometheus для визуализации
- Sentry для отслеживания ошибок и задержек

Пример сбора метрик:

from prometheus_client import start_http_server, Summary
import time
import random

REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')

@REQUEST_TIME.time()
def process_request():
time.sleep(random.random())

if __name__ == '__main__':
start_http_server(8001)
while True:
process_request()


🌐 Масштабирование и развертывание

Когда одна машина уже не тянет, разделяйте:

- API и воркеры — разные контейнеры
- Чтение/запись в БД — через реплики
- Сервис — в k8s или Docker Swarm
- Балансировка — Nginx, HAProxy

Python отлично вписывается в микросервисную инфраструктуру.

💡 Вывод

Python не предназначен быть “голым железом”, как C++, но в грамотных руках — это отличный инструмент для высоконагруженных API, фоновых систем и даже realtime-сервисов. Используйте асинхронность, кэш, очереди, мониторинг — и Python не подведёт.
Создание игр с защитой от читов на Python и PyMunk.
🎮 Python-геймдев и античиты: магия PyMunk под капотом

Вы когда-нибудь задумывались, как в двухмерных играх работают физика и защита от несанкционированного вмешательства? Большинство новичков, погружающихся в разработку игр на Python, в какой-то момент сталкиваются с тем, что их проект слишком легко "взламывается". Давайте разберёмся, как использовать библиотеку PyMunk не только для реалистичной физики, но и в качестве инструмента для защиты вашего игрового мира от читеров.

🛠 Что такое PyMunk

PyMunk — это высокоуровневая обертка над физическим движком Chipmunk2D. Он позволяет просто и понятно внедрять физику в 2D-игры. Но что важнее — PyMunk сам управляет логикой движения объектов, силами и столкновениями. Это значит, что любые попытки напрямую “подкрутить” данные через память или простую модификацию кода станут неэффективны.

🚫 Почему читеры обходят обычную физику

Когда вы пишете игру на Python "на коленке", например:

player.x += 5


Злоумышленнику достаточно изменить значение player.x в отладчике, и его персонаж «телепортируется». Однако если движение объекта вычисляется исключительно в физическом мире движка, вмешательство становится затруднительным.

🧠 PyMunk как физическая истина

Рассмотрим пример, где персонаж управляется через силы, а не напрямую координатами.

import pymunk
import pymunk.pygame_util
import pygame

pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
space = pymunk.Space()
space.gravity = (0, 900)

def create_player(space):
body = pymunk.Body(1, pymunk.moment_for_circle(1, 0, 25))
body.position = 100, 100
shape = pymunk.Circle(body, 25)
shape.elasticity = 0.5
space.add(body, shape)
return body

player_body = create_player(space)
draw_options = pymunk.pygame_util.DrawOptions(screen)

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_body.apply_force_at_local_point((-1500, 0), (0, 0))
if keys[pygame.K_RIGHT]:
player_body.apply_force_at_local_point((1500, 0), (0, 0))

screen.fill((255, 255, 255))
space.step(1/60)
space.debug_draw(draw_options)
pygame.display.flip()
clock.tick(60)

pygame.quit()


Здесь управление персонажем идёт через applyforceatlocalpoint. Координаты тела нельзя "просто так" изменить — сила и масса диктуют движение. Модифицировать player_body.position вручную — бесполезно: на следующем кадре PyMunk всё пересчитает обратно по физике.

🛡 Античит как побочный бонус

Эта архитектура имеет важное преимущество: вы отделяете “визуал” от “реальности”. Даже если кто-то перехватывает ввод или пытается симулировать нажатие клавиш, он не может точно контролировать координаты игрока. А если добавить проверку состояния тел (например, не прыгнул ли игрок без касания земли), можно отловить и навесить флаг “подозрительного поведения”.

Кроме того, движения можно валидировать сервером (если игра сетевого типа) именно на уровне физических параметров: сила, ускорение, импульс. Сравнить два вектора легче, чем разбираться, почему игрок внезапно оказался в стене.

🔒 Финальные советы

- Никогда не давайте игроку прямого доступа к координатам тел.
- Используйте физику, а не “магические” перемещения.
- Логируйте входящие силы и действия — на редкость полезно в отладке и аналитике.
- PyMunk отлично сочетается с серверной проверкой, если решите двигаться к многопользовательским играм.

Итог: PyMunk — это не просто реалистичные прыжки и катящиеся шарики. Это база для создания устойчивой системы геймплея, где поведение игроков подчиняется законам физики, а не желаниям хакера. Если ищете способ сделать игру устойчивее к взлому — используйте физику как истину.
Использование Apache Storm для обработки потоков данных с Python.
Использование Apache Storm для обработки потоков данных с Python.
🔄 Обработка потоков данных с Python и Apache Storm: первая встреча

Всем привет! Сегодня поговорим о чем-то по-настоящему живом — потоковых данных. Представьте Twitter-ленту, клики пользователей на сайте или датчики в IoT — всё это нескончаемые потоки событий. Для их реального времени обработки часто используют Apache Storm. Он мощный, масштабируемый и работает под лозунгом: “боевой зубастый молниеносный фермер потоков”.

Но у Storm есть коварная особенность — родной язык для написания логики обработки данных в нём это Java. К счастью, есть библиотека streamparse — она позволяет писать topologies на Python и запускать их в Apache Storm. Сегодня покажу, как это работает.

📦 Установка

Для начала убедитесь, что у вас установлен Apache Storm (версии 1.x). Далее установим streamparse:

pip install streamparse


Создаём проект:

sparse quickstart storm_example
cd storm_example


Внутри проекта — готовая структура: папки для Spout и Bolt’ов, настройки, зависимости.

🌪 Что такое Spout и Bolt?

Spout — источник данных. Получает события "снаружи": из файла, очереди или API.

Bolt — обрабатывает данные. Например, парсит JSON, считает статистику, отправляет в БД.

Пример: считаем слова в потоке

Создадим Spout, который выдаёт предложения:

from streamparse import Spout
import random

class SentenceSpout(Spout):
def initialize(self, stormconf, context):
self.sentences = ["hello world", "python storm integration", "stream processing rocks"]

def next_tuple(self):
sentence = random.choice(self.sentences)
self.emit([sentence])


Теперь Bolt, который разбивает предложения на слова:

from streamparse import Bolt

class SplitSentenceBolt(Bolt):
def process(self, tup):
sentence = tup.values[0]
for word in sentence.split():
self.emit([word])


И ещё один Bolt, который считает слова:

from streamparse import Bolt
from collections import defaultdict

class WordCountBolt(Bolt):
def initialize(self, conf, ctx):
self.counts = defaultdict(int)

def process(self, tup):
word = tup.values[0]
self.counts[word] += 1
self.log(f"{word}: {self.counts[word]}")


🛠 Запускаем локально

Добавим в файл topologies/wordcount.py описание топологии:

from streamparse import Grouping, Topology
from bolts.word_count import WordCountBolt
from bolts.split_sentence import SplitSentenceBolt
from spouts.sentence import SentenceSpout

class WordCountTopology(Topology):
sentence_spout = SentenceSpout.spec()
splitter_bolt = SplitSentenceBolt.spec(inputs=[sentence_spout])
counter_bolt = WordCountBolt.spec(inputs=[splitter_bolt], par=2)


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

sparse run


Вы увидите, как Apache Storm обрабатывает поток: предложения → слова → счётчики.

🎯 Зачем это нужно?

Apache Storm — не просто блажь ради распределённости. Он умеет:

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

А с помощью streamparse вы сохраняете привычный Python, не углубляясь в джунгли Java.

📌 Вывод

Apache Storm и streamparse позволяют собирать мощные системы потоковой обработки на Python. Это отличный шаг, если вы работаете с реальным временем: логи, метрики, события. Да, он требует установки Java и самого Storm, но в обмен вы получаете надёжный и быстрый фреймворк.

Следующий раз разберём, как подключать Kafka и обрабатывать поток реальных сообщений. А пока — пусть молнии потекут по Python-контактам! 🐍

— Иван.