Как разрабатывать VPN-приложения на основе Python
VPN — это не просто модный термин из мира информационной безопасности. Это реальный рабочий механизм, который позволяет шифровать трафик, обходить блокировки и защищать соединение в публичных сетях. Интересно, что с помощью Python можно построить простое VPN-приложение буквально с нуля — и это совсем не магия, а знание и немного кода.
Основная идея VPN — создание защищённого туннеля между клиентом и сервером, внутри которого весь сетевой трафик проходит в зашифрованном виде. В Python мы можем реализовать подобную функциональность, используя стандартные библиотеки socket и ssl, а также сторонние — такие как pycryptodome для дополнительного шифрования.
Начнем с основы — создадим шифрованное TCP-соединение. Допустим, у нас есть клиент и сервер, которые общаются по TLS:
Пример серверной части:
Пример клиента:
Это уже зашифрованное соединение! На более высоком уровне мы можем добавить маршрут через этот туннель, используя iptables на Linux или прокси-настройки на других системах. Но стоит заметить: этот способ безопасен только внутри локального проекта, для полноценного VPN нужны туннелирование на уровне IP (например, средствами TUN/TAP).
Для работы с такими интерфейсами в Python можно использовать модуль pyroute2 (работает под Linux). Вот пример настройки туннеля:
Создав интерфейс, можно направлять трафик через него и обрабатывать поступающие IP-пакеты с помощью raw-сокетов. Например, чтобы захватить пакеты и переслать через защищённый TCP, мы можем использовать socket.socket с типом
Дополнительно, для шифрования полезной нагрузки можно подключить AES:
Таким образом, VPN-приложение на Python может включать в себя:
- шифрованный TCP-туннель (через ssl);
- работу с сетевыми интерфейсами (через pyroute2);
- обработку и маршрутизацию IP-пакетов (через raw-сокеты и TUN);
- шифрование всех данных (через pycryptodome).
Конечно, это всё требует продуманной архитектуры, обработки ошибок и аутентификации. Настоящий VPN — больше, чем просто код: это защита всего маршрута данных. Но начать проще, чем кажется. Python даёт достаточный инструментарий, чтобы понимать, как всё устроено на самом деле.
Звучит как вызов? Отлично. Потому что любой хороший девелопер любит разбираться в инфраструктуре, не только писать логику веб-приложений. VPN на Python — это именно тот случай, когда ты понимаешь, как работает интернет изнутри.
VPN — это не просто модный термин из мира информационной безопасности. Это реальный рабочий механизм, который позволяет шифровать трафик, обходить блокировки и защищать соединение в публичных сетях. Интересно, что с помощью Python можно построить простое VPN-приложение буквально с нуля — и это совсем не магия, а знание и немного кода.
Основная идея VPN — создание защищённого туннеля между клиентом и сервером, внутри которого весь сетевой трафик проходит в зашифрованном виде. В Python мы можем реализовать подобную функциональность, используя стандартные библиотеки socket и ssl, а также сторонние — такие как pycryptodome для дополнительного шифрования.
Начнем с основы — создадим шифрованное TCP-соединение. Допустим, у нас есть клиент и сервер, которые общаются по TLS:
Пример серверной части:
import socket
import ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile='cert.pem', keyfile='key.pem')
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
bind_socket.bind(('0.0.0.0', 9000))
bind_socket.listen(5)
while True:
new_socket, addr = bind_socket.accept()
conn = context.wrap_socket(new_socket, server_side=True)
data = conn.recv(1024)
print(f"Received: {data}")
conn.sendall(b'Encrypted Hello from VPN Server!')
conn.close()
Пример клиента:
import socket
import ssl
context = ssl.create_default_context()
conn = context.wrap_socket(socket.socket(socket.AF_INET), server_hostname='localhost')
conn.connect(('localhost', 9000))
conn.sendall(b'Hello from Client')
print(f"Server says: {conn.recv(1024)}")
conn.close()
Это уже зашифрованное соединение! На более высоком уровне мы можем добавить маршрут через этот туннель, используя iptables на Linux или прокси-настройки на других системах. Но стоит заметить: этот способ безопасен только внутри локального проекта, для полноценного VPN нужны туннелирование на уровне IP (например, средствами TUN/TAP).
Для работы с такими интерфейсами в Python можно использовать модуль pyroute2 (работает под Linux). Вот пример настройки туннеля:
from pyroute2 import IPRoute
ip = IPRoute()
idx = ip.link_create(ifname='tun0', kind='tun')
ip.addr('add', index=idx, address='10.0.0.1', prefixlen=24)
ip.link('set', index=idx, state='up')
Создав интерфейс, можно направлять трафик через него и обрабатывать поступающие IP-пакеты с помощью raw-сокетов. Например, чтобы захватить пакеты и переслать через защищённый TCP, мы можем использовать socket.socket с типом
socket.SOCK_RAW
.Дополнительно, для шифрования полезной нагрузки можно подключить AES:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_EAX)
data = b'Secret payload'
ciphertext, tag = cipher.encrypt_and_digest(data)
print(ciphertext)
Таким образом, VPN-приложение на Python может включать в себя:
- шифрованный TCP-туннель (через ssl);
- работу с сетевыми интерфейсами (через pyroute2);
- обработку и маршрутизацию IP-пакетов (через raw-сокеты и TUN);
- шифрование всех данных (через pycryptodome).
Конечно, это всё требует продуманной архитектуры, обработки ошибок и аутентификации. Настоящий VPN — больше, чем просто код: это защита всего маршрута данных. Но начать проще, чем кажется. Python даёт достаточный инструментарий, чтобы понимать, как всё устроено на самом деле.
Звучит как вызов? Отлично. Потому что любой хороший девелопер любит разбираться в инфраструктуре, не только писать логику веб-приложений. VPN на Python — это именно тот случай, когда ты понимаешь, как работает интернет изнутри.
👍4❤1
Когда дело доходит до обработки больших объемов данных в реальном времени, на сцену выходит Apache Beam — мощный инструмент с лаконичным API на Python. Эта библиотека позволяет писать единый код как для пакетной, так и для потоковой обработки, который затем можно выполнить на разных движках: Apache Flink, Google Cloud Dataflow, Spark и других.
Представим себе поток логов от веб-приложения: каждый лог — это JSON с информацией о пользователе, времени и действии. Нужно агрегировать количество кликов по страницам — и желательно делать это непрерывно. Как?
Устанавливаем Beam:
Теперь создадим простой pipeline, который будет считать количество кликов по каждой странице за определённый промежуток времени.
Вот что здесь происходит:
- Чтение данных (в реальности это может быть сокет, Kafka или Pub/Sub).
-
-
-
-
Beam заботится о многих "тяжёлых" вещах сам: повторная попытка обработки, управление временем и поздними событиями, масштабирование, параллелизм.
Особенность Beam — в "watermark"-подходе: он умеет понимать, когда данные за конкретное окно можно считать полученными с достаточной полнотой, и тогда он “закрывает” окно. Это делает Beam удобной основой для real-time аналитики в больших системах.
И да, Beam — не замена Pandas или обычному Python-скрипту. Он нужен, когда объёмы данных становятся больше возможностей одной машины, а результаты нужно получать почти мгновенно.
В следующем шаге можно заменить источник данных на
Apache Beam с Python — не просто модный инструмент, а реальный способ построить масштабируемую ETL-систему, которая справится даже с нестабильными потоками от миллионов пользователей. Если вы думали, что Python — язык только для аналитиков, Beam разрушит это представление.
Представим себе поток логов от веб-приложения: каждый лог — это JSON с информацией о пользователе, времени и действии. Нужно агрегировать количество кликов по страницам — и желательно делать это непрерывно. Как?
Устанавливаем Beam:
pip install apache-beam
Теперь создадим простой pipeline, который будет считать количество кликов по каждой странице за определённый промежуток времени.
import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
from datetime import datetime
import json
class ParseEvent(beam.DoFn):
def process(self, element):
event = json.loads(element)
timestamp = datetime.strptime(event['timestamp'], "%Y-%m-%dT%H:%M:%S")
yield beam.window.TimestampedValue(event, timestamp.timestamp())
class ExtractPage(beam.DoFn):
def process(self, event):
yield (event['page'], 1)
with beam.Pipeline(options=PipelineOptions()) as p:
events = (
p
| 'ReadFromSocket' >> beam.io.ReadFromText('events.json') # для простоты: читаем из файла
| 'ParseEvent' >> beam.ParDo(ParseEvent())
| 'WindowIntoFixed' >> beam.WindowInto(beam.window.FixedWindows(60)) # окна по 60 секунд
| 'ExtractPage' >> beam.ParDo(ExtractPage())
| 'CountPerPage' >> beam.CombinePerKey(sum)
| 'PrintResults' >> beam.Map(print)
)
Вот что здесь происходит:
- Чтение данных (в реальности это может быть сокет, Kafka или Pub/Sub).
-
ParseEvent
превращает строку JSON в объект и прикрепляет временную метку, чтобы Beam мог "понять", к какому окну относится событие.-
WindowIntoFixed
разбивает поток по временным окнам — здесь это фиксированные 60-секундные интервалы.-
ExtractPage
— извлекаем имя страницы, по которой был клик.-
CombinePerKey(sum)
— просто считаем количество кликов по каждой странице в каждом окне.Beam заботится о многих "тяжёлых" вещах сам: повторная попытка обработки, управление временем и поздними событиями, масштабирование, параллелизм.
Особенность Beam — в "watermark"-подходе: он умеет понимать, когда данные за конкретное окно можно считать полученными с достаточной полнотой, и тогда он “закрывает” окно. Это делает Beam удобной основой для real-time аналитики в больших системах.
И да, Beam — не замена Pandas или обычному Python-скрипту. Он нужен, когда объёмы данных становятся больше возможностей одной машины, а результаты нужно получать почти мгновенно.
В следующем шаге можно заменить источник данных на
apache_beam.io.kafka.ReadFromKafka
, использовать сессионные окна или включить таймеры — всё, как в серии про настоящую потоковую обработку данных.Apache Beam с Python — не просто модный инструмент, а реальный способ построить масштабируемую ETL-систему, которая справится даже с нестабильными потоками от миллионов пользователей. Если вы думали, что Python — язык только для аналитиков, Beam разрушит это представление.
На этой неделе я решил затронуть тему, которая волнует многих начинающих разработчиков: создание собственной системы управления контентом (CMS) на Django. Часто при изучении фреймворка мы учимся делать блоги, страницы и формы. Но что, если попробовать сделать нечто большее — свою CMS? Управляемый контент, возможность редактирования без кода, гибкое расширение — звучит вдохновляюще? Тогда поехали.
С чего начать? Django уже практически готов для построения CMS. У него есть админка, модели, формы, авторизация, шаблоны — всё, что нужно новичку для уверенного старта.
Создадим базу: установим Django и создадим проект.
В core создаём первую модель — ContentPage:
Подключим её в админку:
Теперь, зайдя в admin-панель, можно добавлять страницы с уникальным slug и текстом. Но наша цель — чтобы эти страницы отдавались по соответствующему URL, не создавая вручную views под каждую.
Создаём "умный" view:
И URL-шаблон:
Всё. Теперь любой контент с определённым slug — например, "about" — будет доступен по адресу /about/. Но что, если хотим, чтобы администратор мог задавать не только текст, но и типы блоков? Представим блок "цитата", "изображение + текст", "галерея".
Решение: отдельные модели блоков.
Теперь страницы можно собирать как конструктор: добавлять разнообразные блоки, управлять их порядком. Через админку пользователь собирает страницу сам, без кода. В шаблоне просто итерируем blocks и отображаем нужный HTML под каждый тип:
Хочется вложений страниц, как у real CMS? Добавим parent-связь в ContentPage и дорисуем древовидную структуру — можно с помощью django-mptt.
Хотим редактор, вместо plain TextField? Подключаем django-ckeditor и получаем визуальную обработку контента.
В этой архитектуре вся мощь CMS оказывается в руках администратора: он создаёт новые страницы, меняет их, комбинирует блоки — без программирования. Мы же, как разработчики, создаём каркас и логику.
Таким образом, используя стандартный инструментарий Django, мы получаем лёгкую, настраиваемую и расширяемую CMS. Не надо ждать "идеальную" CMS от третьих лиц — можно построить свою. Понятную, минималистичную и под конкретные задачи. И это, по моему личному опыту, куда ценнее универсальных монстров.
С чего начать? Django уже практически готов для построения CMS. У него есть админка, модели, формы, авторизация, шаблоны — всё, что нужно новичку для уверенного старта.
Создадим базу: установим Django и создадим проект.
django-admin startproject cms_project
cd cms_project
python manage.py startapp core
В core создаём первую модель — ContentPage:
from django.db import models
class ContentPage(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Подключим её в админку:
from django.contrib import admin
from .models import ContentPage
admin.site.register(ContentPage)
Теперь, зайдя в admin-панель, можно добавлять страницы с уникальным slug и текстом. Но наша цель — чтобы эти страницы отдавались по соответствующему URL, не создавая вручную views под каждую.
Создаём "умный" view:
from django.shortcuts import get_object_or_404, render
from .models import ContentPage
def content_page_view(request, slug):
page = get_object_or_404(ContentPage, slug=slug)
return render(request, 'core/page.html', {'page': page})
И URL-шаблон:
from django.urls import path
from .views import content_page_view
urlpatterns = [
path('<slug:slug>/', content_page_view, name='content_page'),
]
Всё. Теперь любой контент с определённым slug — например, "about" — будет доступен по адресу /about/. Но что, если хотим, чтобы администратор мог задавать не только текст, но и типы блоков? Представим блок "цитата", "изображение + текст", "галерея".
Решение: отдельные модели блоков.
class PageBlock(models.Model):
page = models.ForeignKey(ContentPage, related_name='blocks', on_delete=models.CASCADE)
block_type = models.CharField(max_length=50, choices=[
('text', 'Text'),
('quote', 'Quote'),
('image', 'Image'),
])
content = models.TextField()
order = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['order']
Теперь страницы можно собирать как конструктор: добавлять разнообразные блоки, управлять их порядком. Через админку пользователь собирает страницу сам, без кода. В шаблоне просто итерируем blocks и отображаем нужный HTML под каждый тип:
{% for block in page.blocks.all %}
{% if block.block_type == 'text' %}
<p>{{ block.content }}</p>
{% elif block.block_type == 'quote' %}
<blockquote>{{ block.content }}</blockquote>
{% elif block.block_type == 'image' %}
<img src="{{ block.content }}" alt="Image block">
{% endif %}
{% endfor %}
Хочется вложений страниц, как у real CMS? Добавим parent-связь в ContentPage и дорисуем древовидную структуру — можно с помощью django-mptt.
Хотим редактор, вместо plain TextField? Подключаем django-ckeditor и получаем визуальную обработку контента.
В этой архитектуре вся мощь CMS оказывается в руках администратора: он создаёт новые страницы, меняет их, комбинирует блоки — без программирования. Мы же, как разработчики, создаём каркас и логику.
Таким образом, используя стандартный инструментарий Django, мы получаем лёгкую, настраиваемую и расширяемую CMS. Не надо ждать "идеальную" CMS от третьих лиц — можно построить свою. Понятную, минималистичную и под конкретные задачи. И это, по моему личному опыту, куда ценнее универсальных монстров.
👍1
Если вы разработчик, архитектор или просто любите порядок — пора познакомиться с BPMN. Это не аббревиатура очередного круизного лайнера, а Business Process Model and Notation — нотация для моделирования бизнес-процессов. Грубо говоря, это способ рисовать понятные схемы с задачами, условиями, событиями и участниками, чтобы визуализировать, как работает система. И знаете что? Создавать такие диаграммы можно прямо из Python.
Давайте разберемся, как программно строить BPMN-диаграммы. На помощь приходит библиотека bpmn-python. Она позволяет описывать процесс на языке Python и экспортировать его в формат BPMN 2.0 — достаточно, чтобы открыть в любом визуальном редакторе, например, Camunda Modeler или bpmn.io.
Устанавливаем:
Теперь — минимальный пример, как это выглядит:
Что происходит: мы создаём процесс "Order Process", добавляем стартовое событие, задачу, условный шлюз (эксклюзивный gateway) и завершающее событие. Затем соединяем элементы стрелками. В итоге получаем изображение диаграммы — понятно и без слов.
BPMN хорош тем, что легко читается — даже менеджер без технического фона поймёт, что происходит в вашем процессе. Кроме того, такая визуализация помогает выявить узкие места и лишнюю логику ещё на этапе проектирования.
Если хочется усложнить сценарий — добавьте участника (пул или дорожку), события сообщений, циклические задачи и параллельные шлюзы. Всё это поддерживается в bpmn-python, хоть и не всегда очевидно — документация скромная. Тем не менее, для генерации базовых бизнес-процессов инструмента достаточно.
В мире, где почти каждый API, микросервис и скрипт становится частью сложного потока, визуализация таких процессов ценится на вес золота. А когда эту визуализацию можно собрать автоматически из Python — это становится частью DevOps-магии.
Давайте разберемся, как программно строить BPMN-диаграммы. На помощь приходит библиотека bpmn-python. Она позволяет описывать процесс на языке Python и экспортировать его в формат BPMN 2.0 — достаточно, чтобы открыть в любом визуальном редакторе, например, Camunda Modeler или bpmn.io.
Устанавливаем:
pip install bpmn-python
Теперь — минимальный пример, как это выглядит:
from bpmn_python.bpmn_diagram_rep import BpmnDiagramGraph
from bpmn_python.bpmn_diagram_drawer import BpmnDiagramDrawer
diagram = BpmnDiagramGraph()
process_id = diagram.create_new_process_diagram_graph(diagram_name='Order Process')
start_event_id = diagram.add_start_event_to_diagram(process_id, 'StartOrder')
task_id = diagram.add_task_to_diagram(process_id, 'ReceiveOrder')
gateway_id = diagram.add_exclusive_gateway_to_diagram(process_id, 'CheckStock')
end_event_id = diagram.add_end_event_to_diagram(process_id, 'EndProcess')
diagram.add_sequence_flow_to_diagram(process_id, start_event_id, task_id)
diagram.add_sequence_flow_to_diagram(process_id, task_id, gateway_id)
diagram.add_sequence_flow_to_diagram(process_id, gateway_id, end_event_id)
drawer = BpmnDiagramDrawer()
drawer.bpmn_graph = diagram
drawer.draw_diagram(output_path='order_process_diagram.png')
Что происходит: мы создаём процесс "Order Process", добавляем стартовое событие, задачу, условный шлюз (эксклюзивный gateway) и завершающее событие. Затем соединяем элементы стрелками. В итоге получаем изображение диаграммы — понятно и без слов.
BPMN хорош тем, что легко читается — даже менеджер без технического фона поймёт, что происходит в вашем процессе. Кроме того, такая визуализация помогает выявить узкие места и лишнюю логику ещё на этапе проектирования.
Если хочется усложнить сценарий — добавьте участника (пул или дорожку), события сообщений, циклические задачи и параллельные шлюзы. Всё это поддерживается в bpmn-python, хоть и не всегда очевидно — документация скромная. Тем не менее, для генерации базовых бизнес-процессов инструмента достаточно.
В мире, где почти каждый API, микросервис и скрипт становится частью сложного потока, визуализация таких процессов ценится на вес золота. А когда эту визуализацию можно собрать автоматически из Python — это становится частью DevOps-магии.
👍1
Привет, друзья! Сегодня нырнем в мир асинхронности и узнаем, как Python-тюлень превращается в сетевую торпеду благодаря библиотеке asyncio. Если вы когда-либо писали сетевые приложения и сталкивались с болью от блокирующего кода — добро пожаловать в будущее, где одна корутина может сделать больше, чем десять потоков на слабом ноутбуке.
Что же такое asyncio? Это современный подход к асинхронному программированию в Python. Он позволяет запускать несколько задач одновременно без реального многопоточия — за счёт кооперативной многозадачности. Это идеальный выбор для I/O-зависимых задач: работы с сетью, файлами, сокетами и базами данных.
Рассмотрим пример простого TCP-сервера, который обрабатывает клиентские соединения асинхронно:
import asyncio
async def handleclient(reader, writer):
addr = writer.getextrainfo('peername')
print(f"Connected: {addr}")
while True:
data = await reader.readline()
if not data:
break
message = data.decode().strip()
print(f"Received from {addr}: {message}")
response = f"Echo: {message}\n"
writer.write(response.encode())
await writer.drain()
print(f"Disconnected: {addr}")
writer.close()
await writer.waitclosed()
async def main():
server = await asyncio.startserver(handleclient, '127.0.0.1', 8888)
addr = server.sockets0.getsockname()
print(f"Serving on {addr}")
async with server:
await server.serveforever()
asyncio.run(main())
Этот код запускает асинхронный TCP-сервер на порту 8888. При подключении клиента создается новая корутина handleclient. Вместо блокирующих операций чтения/записи мы используем await reader.readline() и await writer.drain(), позволяя другим задачам выполняться между ожиданиями.
Чем это лучше, скажете вы? Ну, во-первых — экономия ресурсов. Вместо того чтобы спаунить потоки и платить за переключение контекста (и риск словить GIL), asyncio даёт нам лёгкие задачи внутри одного потока. Во-вторых — читаемость. Вместо колбэков и адской вложенности в стиле JavaScript времён динозавров, у нас есть async/await — лаконично и выразительно.
Допустим, вы хотите написать клиент, который периодически шлёт сообщения серверу:
async def tcpechoclient():
reader, writer = await asyncio.openconnection('127.0.0.1', 8888)
for i in range(5):
message = f"Hello {i}\n"
writer.write(message.encode())
await writer.drain()
response = await reader.readline()
print(f"Received: {response.decode().strip()}")
await asyncio.sleep(1)
writer.close()
await writer.waitclosed()
asyncio.run(tcpechoclient())
Это уже мини-болталка: клиент отправляет сообщения, сервер эхо-отвечает. Всё асинхронно и без блокировок! А если подключатся десятки клиентов? Никаких проблем — asyncio справится, пока вы не начнете жарить процессор тяжёлыми вычислениями. Тут уже стоит подумать об asyncio + multiprocessing или выносить нагрузку в отдельные сервисы.
А как быть с тайм-аутами, отменой задач и очередями? Тут тоже всё продумано: asyncio предоставляет объекты Future, Task и Queue, которые позволяют строить настоящие архитектуры. И, да, в реальных проектах часто используются такие фреймворки, как aiohttp (асинхронный HTTP-сервер и клиент) или websockets — они расширяют возможности asyncio, сохраняя модели async/await.
asyncio — это мощный инструмент, который делает написание сетевых приложений в Python одновременно простым, эффективным и масштабируемым. Если вы до сих пор пишете blocking-сокеты — самое время пересесть на асинхронный экспресс.
До встречи в следующих постах, где мы разберём, как с помощью aiohttp строить REST API, не теряя скорости даже под нагрузкой.
Что же такое asyncio? Это современный подход к асинхронному программированию в Python. Он позволяет запускать несколько задач одновременно без реального многопоточия — за счёт кооперативной многозадачности. Это идеальный выбор для I/O-зависимых задач: работы с сетью, файлами, сокетами и базами данных.
Рассмотрим пример простого TCP-сервера, который обрабатывает клиентские соединения асинхронно:
import asyncio
async def handleclient(reader, writer):
addr = writer.getextrainfo('peername')
print(f"Connected: {addr}")
while True:
data = await reader.readline()
if not data:
break
message = data.decode().strip()
print(f"Received from {addr}: {message}")
response = f"Echo: {message}\n"
writer.write(response.encode())
await writer.drain()
print(f"Disconnected: {addr}")
writer.close()
await writer.waitclosed()
async def main():
server = await asyncio.startserver(handleclient, '127.0.0.1', 8888)
addr = server.sockets0.getsockname()
print(f"Serving on {addr}")
async with server:
await server.serveforever()
asyncio.run(main())
Этот код запускает асинхронный TCP-сервер на порту 8888. При подключении клиента создается новая корутина handleclient. Вместо блокирующих операций чтения/записи мы используем await reader.readline() и await writer.drain(), позволяя другим задачам выполняться между ожиданиями.
Чем это лучше, скажете вы? Ну, во-первых — экономия ресурсов. Вместо того чтобы спаунить потоки и платить за переключение контекста (и риск словить GIL), asyncio даёт нам лёгкие задачи внутри одного потока. Во-вторых — читаемость. Вместо колбэков и адской вложенности в стиле JavaScript времён динозавров, у нас есть async/await — лаконично и выразительно.
Допустим, вы хотите написать клиент, который периодически шлёт сообщения серверу:
async def tcpechoclient():
reader, writer = await asyncio.openconnection('127.0.0.1', 8888)
for i in range(5):
message = f"Hello {i}\n"
writer.write(message.encode())
await writer.drain()
response = await reader.readline()
print(f"Received: {response.decode().strip()}")
await asyncio.sleep(1)
writer.close()
await writer.waitclosed()
asyncio.run(tcpechoclient())
Это уже мини-болталка: клиент отправляет сообщения, сервер эхо-отвечает. Всё асинхронно и без блокировок! А если подключатся десятки клиентов? Никаких проблем — asyncio справится, пока вы не начнете жарить процессор тяжёлыми вычислениями. Тут уже стоит подумать об asyncio + multiprocessing или выносить нагрузку в отдельные сервисы.
А как быть с тайм-аутами, отменой задач и очередями? Тут тоже всё продумано: asyncio предоставляет объекты Future, Task и Queue, которые позволяют строить настоящие архитектуры. И, да, в реальных проектах часто используются такие фреймворки, как aiohttp (асинхронный HTTP-сервер и клиент) или websockets — они расширяют возможности asyncio, сохраняя модели async/await.
asyncio — это мощный инструмент, который делает написание сетевых приложений в Python одновременно простым, эффективным и масштабируемым. Если вы до сих пор пишете blocking-сокеты — самое время пересесть на асинхронный экспресс.
До встречи в следующих постах, где мы разберём, как с помощью aiohttp строить REST API, не теряя скорости даже под нагрузкой.
🔥4
Рекомендации, которые понимают тебя лучше, чем друзья? Звучит как магия! Но на самом деле — это математика и немного Python. Сегодня мы погрузимся в мир рекомендационных систем и узнаем, как с их помощью можно строить персонализированные советы — будь то фильмы, книги или товары. А точнее — разберём один из самых популярных подходов: Collaborative Filtering.
Что такое Collaborative Filtering?
Это метод, который работает по следующей логике: «Если пользователь A и пользователь B оценили много объектов одинаково, то, скорее всего, то, что понравилось B, понравится и A». В этом подходе нет необходимости знать содержимое самих объектов — только поведение пользователей.
В Python есть несколько удобных библиотек для реализации коллаборативной фильтрации. Для базовой версии отлично подойдёт библиотека Surprise (да, именно так называется — она действительно способна удивить).
Установим её:
pip install scikit-surprise
Теперь время кода:
from surprise import Dataset, Reader
from surprise import KNNBasic
from surprise.modelselection import traintestsplit
from surprise import accuracy
# Пример данных: userid, itemid, rating (1–5)
data = Dataset.loadfromdf(
[
("user1", "item1", 5),
("user1", "item2", 3),
("user2", "item1", 4),
("user2", "item3", 2),
("user3", "item2", 4),
("user3", "item3", 5),
],
Reader(ratingscale=(1, 5))
)
trainset, testset = traintestsplit(data, testsize=0.2)
# Модель на основе user-based collaborative filtering
algo = KNNBasic(simoptions={"userbased": True})
algo.fit(trainset)
predictions = algo.test(testset)
# Посмотрим на точность
print(f"RMSE: {accuracy.rmse(predictions):.4f}")
# Предсказать интерес пользователя
userid = "user1"
itemid = "item3"
pred = algo.predict(userid, itemid)
print(f"Predicted rating for {userid} on {itemid}: {pred.est:.2f}")
Что тут происходит? Мы берём искусственный датафрейм с оценками пользователей, делим данные на тренировочные и тестовые, строим модель на K-ближайших соседях, основываясь на схожести пользователей. А потом... начинаем предсказывать, насколько понравится товар user1, если он ещё не взаимодействовал с ним.
Можно легко переключиться на item-based подход, просто поменяв userbased на False — тогда схожесть будет оцениваться между объектами, что тоже иногда даёт отличные результаты.
Этот метод прост, но прекрасно работает на небольших датасетах или как базовая модель. Реальные системы, конечно, используют матричные разложения и глубокие нейронные сети. Но с чего-то ведь нужно начинать, верно?
Так что если вы хотите построить своему пользователю «Netflix в миниатюре» — попробуйте collaborative filtering. Это не так сложно, как кажется, особенно с Python в руках.
Что такое Collaborative Filtering?
Это метод, который работает по следующей логике: «Если пользователь A и пользователь B оценили много объектов одинаково, то, скорее всего, то, что понравилось B, понравится и A». В этом подходе нет необходимости знать содержимое самих объектов — только поведение пользователей.
В Python есть несколько удобных библиотек для реализации коллаборативной фильтрации. Для базовой версии отлично подойдёт библиотека Surprise (да, именно так называется — она действительно способна удивить).
Установим её:
pip install scikit-surprise
Теперь время кода:
from surprise import Dataset, Reader
from surprise import KNNBasic
from surprise.modelselection import traintestsplit
from surprise import accuracy
# Пример данных: userid, itemid, rating (1–5)
data = Dataset.loadfromdf(
[
("user1", "item1", 5),
("user1", "item2", 3),
("user2", "item1", 4),
("user2", "item3", 2),
("user3", "item2", 4),
("user3", "item3", 5),
],
Reader(ratingscale=(1, 5))
)
trainset, testset = traintestsplit(data, testsize=0.2)
# Модель на основе user-based collaborative filtering
algo = KNNBasic(simoptions={"userbased": True})
algo.fit(trainset)
predictions = algo.test(testset)
# Посмотрим на точность
print(f"RMSE: {accuracy.rmse(predictions):.4f}")
# Предсказать интерес пользователя
userid = "user1"
itemid = "item3"
pred = algo.predict(userid, itemid)
print(f"Predicted rating for {userid} on {itemid}: {pred.est:.2f}")
Что тут происходит? Мы берём искусственный датафрейм с оценками пользователей, делим данные на тренировочные и тестовые, строим модель на K-ближайших соседях, основываясь на схожести пользователей. А потом... начинаем предсказывать, насколько понравится товар user1, если он ещё не взаимодействовал с ним.
Можно легко переключиться на item-based подход, просто поменяв userbased на False — тогда схожесть будет оцениваться между объектами, что тоже иногда даёт отличные результаты.
Этот метод прост, но прекрасно работает на небольших датасетах или как базовая модель. Реальные системы, конечно, используют матричные разложения и глубокие нейронные сети. Но с чего-то ведь нужно начинать, верно?
Так что если вы хотите построить своему пользователю «Netflix в миниатюре» — попробуйте collaborative filtering. Это не так сложно, как кажется, особенно с Python в руках.
Вы когда-нибудь оказались в ситуации, когда нужно сгенерировать отчет с сотнями строк данных, а затем каждую неделю обновлять его вручную? Excel зависает, числа в глазах двоятся, а дедлайны дышат в затылок. В такой момент Python становится супергероем офисной автоматизации. Сегодня я покажу, как автоматизировать создание и обновление отчетов с помощью Python — быстро, просто и без боли.
На помощь приходят проверенные бойцы: pandas, openpyxl и matplotlib. Они помогут работать с данными, редактировать Excel-файлы и даже строить графики. Начнем с простого отчета: есть CSV-файл с продажами по регионам, нам нужно собрать сумму продаж, построить график и сохранить всё это в Excel-отчет.
Пример исходных данных в sales.csv:
region,date,sales
North,2024-05-01,1200
South,2024-05-01,950
North,2024-05-02,1340
... и так далее.
Сначала читаем и обрабатываем данные:
Хотим добавить график, чтобы отчет был не только полезный, но и красивый? Без проблем:
Теперь создаем Excel-файл с таблицей и вставляем туда наш график:
Что получилось: из CSV-файла мы автоматически получили сводную таблицу по регионам, построили визуализацию и сохранили все это в виде Excel-файла. Всё генерируется буквально за секунды. Можно запускать этот скрипт каждый день или неделю через планировщик задач — и больше не мучиться с отчетами вручную.
Если добавить немножко логики — например, проверку за какую дату данные, или отправку итогового файла по email через smtplib — автоматизация выходит на новый уровень.
Python не просто сокращает время, он освобождает его. Отчеты, которые раньше отнимали часы, можно теперь генерировать в одно касание. И вместо унылого копирования цифр — больше времени на анализ, развитие и создание чего-то действительно важного.
На помощь приходят проверенные бойцы: pandas, openpyxl и matplotlib. Они помогут работать с данными, редактировать Excel-файлы и даже строить графики. Начнем с простого отчета: есть CSV-файл с продажами по регионам, нам нужно собрать сумму продаж, построить график и сохранить всё это в Excel-отчет.
Пример исходных данных в sales.csv:
region,date,sales
North,2024-05-01,1200
South,2024-05-01,950
North,2024-05-02,1340
... и так далее.
Сначала читаем и обрабатываем данные:
import pandas as pd
data = pd.read_csv("sales.csv", parse_dates=["date"])
summary = data.groupby("region")["sales"].sum().reset_index()
Хотим добавить график, чтобы отчет был не только полезный, но и красивый? Без проблем:
import matplotlib.pyplot as plt
plt.figure(figsize=(6, 4))
plt.bar(summary["region"], summary["sales"], color="skyblue")
plt.title("Sales by Region")
plt.xlabel("Region")
plt.ylabel("Total Sales")
plt.tight_layout()
plt.savefig("sales_chart.png")
plt.close()
Теперь создаем Excel-файл с таблицей и вставляем туда наш график:
from openpyxl import Workbook
from openpyxl.drawing.image import Image
from openpyxl.utils.dataframe import dataframe_to_rows
wb = Workbook()
ws = wb.active
ws.title = "Sales Report"
# Вставляем таблицу
for row in dataframe_to_rows(summary, index=False, header=True):
ws.append(row)
# Вставляем картинку с графиком
img = Image("sales_chart.png")
img.anchor = "E2" # координаты вставки
ws.add_image(img)
wb.save("sales_report.xlsx")
Что получилось: из CSV-файла мы автоматически получили сводную таблицу по регионам, построили визуализацию и сохранили все это в виде Excel-файла. Всё генерируется буквально за секунды. Можно запускать этот скрипт каждый день или неделю через планировщик задач — и больше не мучиться с отчетами вручную.
Если добавить немножко логики — например, проверку за какую дату данные, или отправку итогового файла по email через smtplib — автоматизация выходит на новый уровень.
Python не просто сокращает время, он освобождает его. Отчеты, которые раньше отнимали часы, можно теперь генерировать в одно касание. И вместо унылого копирования цифр — больше времени на анализ, развитие и создание чего-то действительно важного.
👍1
Когда дело доходит до обработки изображений, Python уже давно считается мощным инструментом: PIL, OpenCV, NumPy — все это знакомо многим. Но что, если скорость критична, а массивы пикселей требуют обработки параллельно? Добро пожаловать в мир OpenCL.
OpenCL (Open Computing Language) — это фреймворк для написания программ, которые исполняются на гетерогенных устройствах: CPU, GPU и других ускорителях. Да, это немного ближе к низкому уровню, но Python умеет работать с этим элегантно благодаря библиотеке PyOpenCL.
Сегодня мы разберем, как писать простой код на Python для обработки изображения с использованием OpenCL: от чтения файла до применения фильтра размытия с GPU.
Установка PyOpenCL:
pip install pyopencl Pillow numpy
Пример: фильтр размытия изображения.
Начнем с загрузки изображения и подготовки его к обработке:
from PIL import Image
import pyopencl as cl
import numpy as np
# Загрузка изображения
img = Image.open("input.jpg").convert("L") # Преобразуем в оттенки серого
imgarray = np.array(img).astype(np.uint8)
height, width = imgarray.shape
# Подготовка выходного массива
resultarray = np.emptylike(imgarray)
Теперь создаем контекст OpenCL и компилируем ядро:
ctx = cl.createsomecontext()
queue = cl.CommandQueue(ctx)
# OpenCL-ядро для размытия
kernelcode = """
kernel void blurimage(global const uchar *input,
global uchar *output,
const int width,
const int height) {
int x = getglobalid(0);
int y = getglobalid(1);
int idx = y * width + x;
if (x > 0 && y > 0 && x < width - 1 && y < height - 1) {
int sum = 0;
for (int dx = -1; dx <= 1; dx++)
for (int dy = -1; dy <= 1; dy++) {
int nx = x + dx;
int ny = y + dy;
sum += input[ny * width + nx];
}
output[idx] = sum / 9;
} else {
output[idx] = input[idx];
}
}
"""
program = cl.Program(ctx, kernelcode).build()
# Создание буферов
mf = cl.memflags
inputbuf = cl.Buffer(ctx, mf.READONLY | mf.COPYHOSTPTR, hostbuf=imgarray)
outputbuf = cl.Buffer(ctx, mf.WRITEONLY, resultarray.nbytes)
# Запуск ядра
program.blurimage(queue, (width, height), None,
inputbuf, outputbuf,
np.int32(width), np.int32(height))
# Копирование результата обратно
cl.enqueuecopy(queue, resultarray, outputbuf)
# Сохранение выходного изображения
Image.fromarray(resultarray).save("output.jpg")
Что мы сделали:
- Считали изображение и преобразовали в массив.
- Подали его в ядро OpenCL, в котором политики памяти максимально эффективны.
- Обработали каждый пиксель параллельно, благодаря GPU.
- Получили примерно в 10-20 раз более быструю обработку по сравнению с чистым Python.
Почему это важно?
Когда вы имеете дело с изображениями высокого разрешения, производительность становится критична. Даже простое размытие может занимать секунды. OpenCL позволяет разгрузить CPU, переложив вычисления на GPU, даже встроенный.
К тому же, PyOpenCL — это не просто мост между Python и OpenCL. Он предоставляет удобные средства работы с памятью, компиляцией и управления устройствами.
Заключение
Если вы работаете с изображениями и чувствуете, что Python не справляется, не спешите уходить к C++. PyOpenCL — мощный способ ускорить вычисления, не теряя гибкости Python. Попробуйте, результат вас удивит.
OpenCL (Open Computing Language) — это фреймворк для написания программ, которые исполняются на гетерогенных устройствах: CPU, GPU и других ускорителях. Да, это немного ближе к низкому уровню, но Python умеет работать с этим элегантно благодаря библиотеке PyOpenCL.
Сегодня мы разберем, как писать простой код на Python для обработки изображения с использованием OpenCL: от чтения файла до применения фильтра размытия с GPU.
Установка PyOpenCL:
pip install pyopencl Pillow numpy
Пример: фильтр размытия изображения.
Начнем с загрузки изображения и подготовки его к обработке:
from PIL import Image
import pyopencl as cl
import numpy as np
# Загрузка изображения
img = Image.open("input.jpg").convert("L") # Преобразуем в оттенки серого
imgarray = np.array(img).astype(np.uint8)
height, width = imgarray.shape
# Подготовка выходного массива
resultarray = np.emptylike(imgarray)
Теперь создаем контекст OpenCL и компилируем ядро:
ctx = cl.createsomecontext()
queue = cl.CommandQueue(ctx)
# OpenCL-ядро для размытия
kernelcode = """
kernel void blurimage(global const uchar *input,
global uchar *output,
const int width,
const int height) {
int x = getglobalid(0);
int y = getglobalid(1);
int idx = y * width + x;
if (x > 0 && y > 0 && x < width - 1 && y < height - 1) {
int sum = 0;
for (int dx = -1; dx <= 1; dx++)
for (int dy = -1; dy <= 1; dy++) {
int nx = x + dx;
int ny = y + dy;
sum += input[ny * width + nx];
}
output[idx] = sum / 9;
} else {
output[idx] = input[idx];
}
}
"""
program = cl.Program(ctx, kernelcode).build()
# Создание буферов
mf = cl.memflags
inputbuf = cl.Buffer(ctx, mf.READONLY | mf.COPYHOSTPTR, hostbuf=imgarray)
outputbuf = cl.Buffer(ctx, mf.WRITEONLY, resultarray.nbytes)
# Запуск ядра
program.blurimage(queue, (width, height), None,
inputbuf, outputbuf,
np.int32(width), np.int32(height))
# Копирование результата обратно
cl.enqueuecopy(queue, resultarray, outputbuf)
# Сохранение выходного изображения
Image.fromarray(resultarray).save("output.jpg")
Что мы сделали:
- Считали изображение и преобразовали в массив.
- Подали его в ядро OpenCL, в котором политики памяти максимально эффективны.
- Обработали каждый пиксель параллельно, благодаря GPU.
- Получили примерно в 10-20 раз более быструю обработку по сравнению с чистым Python.
Почему это важно?
Когда вы имеете дело с изображениями высокого разрешения, производительность становится критична. Даже простое размытие может занимать секунды. OpenCL позволяет разгрузить CPU, переложив вычисления на GPU, даже встроенный.
К тому же, PyOpenCL — это не просто мост между Python и OpenCL. Он предоставляет удобные средства работы с памятью, компиляцией и управления устройствами.
Заключение
Если вы работаете с изображениями и чувствуете, что Python не справляется, не спешите уходить к C++. PyOpenCL — мощный способ ускорить вычисления, не теряя гибкости Python. Попробуйте, результат вас удивит.
Многоязычие в Django: как заставить ваше приложение "говорить" по-английски, по-русски и не только
Создаёте веб-приложение и хотите, чтобы им пользовались люди со всего мира? Добро пожаловать в мульти-языковой мир Django. Этот фреймворк предоставляет полноценные средства для локализации интерфейсов — от перевода текстов до управления пользовательскими языковыми настройками. Ниже — конкретно и без воды о том, как всё это настроить.
🔹 Шаг 1: Включим поддержку перевода
В
Параметр
🔹 Шаг 2: Готовим строки к переводу
Все строки, которые должны быть переведены, нужно пометить специальными функциями. Django предоставляет
Пример в шаблоне:
Пример в Python-коде:
🔹 Шаг 3: Собираем переводимые строки
После пометок — соберём все строки для перевода. Выполняем команду:
В результате появится файл
🔹 Шаг 4: Компилируем переводы
Чтобы Django мог использовать переведённые строки, необходимо скомпилировать
Теперь переводы готовы к использованию.
🔹 Шаг 5: Автоматическое определение языка
Добавьте
Этот middleware анализирует заголовки браузера или куки и подставляет нужный язык.
Хотите переключать язык вручную? Создайте URL:
Теперь URL-адрес будет содержать префикс языка (
🔹 Шаг 6: Динамическое переключение языка
Можно переключать язык прямо во время выполнения, например, через форму или селектор:
🎉 Готово!
Теперь ваше Django-приложение умеет "разговаривать" на нескольких языках. Это открывает дорогу к глобальному рынку и делает интерфейс дружелюбнее к пользователю.
Локализация в Django — это не просто nice-to-have. Это must-have, если вы хотите выйти за пределы одного языка. Делая ваш сайт многоязычным, вы делаете его доступным. А значит — полезным.
Создаёте веб-приложение и хотите, чтобы им пользовались люди со всего мира? Добро пожаловать в мульти-языковой мир Django. Этот фреймворк предоставляет полноценные средства для локализации интерфейсов — от перевода текстов до управления пользовательскими языковыми настройками. Ниже — конкретно и без воды о том, как всё это настроить.
🔹 Шаг 1: Включим поддержку перевода
В
settings.py
активируем интернационализацию:USE_I18N = True
USE_L10N = True
LANGUAGE_CODE = 'en'
LANGUAGES = [
('en', 'English'),
('ru', 'Russian'),
]
LOCALE_PATHS = [
BASE_DIR / 'locale',
]
Параметр
LANGUAGES
важен — это список поддерживаемых языков. Именно здесь вы определяете, на какие языки будет переведён ваш интерфейс.🔹 Шаг 2: Готовим строки к переводу
Все строки, которые должны быть переведены, нужно пометить специальными функциями. Django предоставляет
gettext()
и gettext_lazy()
(чаще используется ugettext_lazy
, но начиная с Django 4.0 используется просто gettext_lazy
).Пример в шаблоне:
<h1>{% trans "Welcome to my website!" %}</h1>
Пример в Python-коде:
from django.utils.translation import gettext_lazy as _
class Product(models.Model):
name = models.CharField(max_length=100, verbose_name=_("Product Name"))
🔹 Шаг 3: Собираем переводимые строки
После пометок — соберём все строки для перевода. Выполняем команду:
django-admin makemessages -l ru
В результате появится файл
locale/ru/LC_MESSAGES/django.po
. Именно в нём вы вписываете переводы:msgid "Welcome to my website!"
msgstr "Добро пожаловать на мой сайт!"
🔹 Шаг 4: Компилируем переводы
Чтобы Django мог использовать переведённые строки, необходимо скомпилировать
.po
в .mo
:django-admin compilemessages
Теперь переводы готовы к использованию.
🔹 Шаг 5: Автоматическое определение языка
Добавьте
LocaleMiddleware
в MIDDLEWARE
:MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware',
# ...
]
Этот middleware анализирует заголовки браузера или куки и подставляет нужный язык.
Хотите переключать язык вручную? Создайте URL:
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
path('admin/', admin.site.urls),
path('products/', include('products.urls')),
)
Теперь URL-адрес будет содержать префикс языка (
/ru/products/
), а Django подстроится под локаль.🔹 Шаг 6: Динамическое переключение языка
Можно переключать язык прямо во время выполнения, например, через форму или селектор:
from django.utils import translation
def set_language_view(request):
user_language = 'ru'
translation.activate(user_language)
response = HttpResponse("Привет!")
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_language)
return response
🎉 Готово!
Теперь ваше Django-приложение умеет "разговаривать" на нескольких языках. Это открывает дорогу к глобальному рынку и делает интерфейс дружелюбнее к пользователю.
Локализация в Django — это не просто nice-to-have. Это must-have, если вы хотите выйти за пределы одного языка. Делая ваш сайт многоязычным, вы делаете его доступным. А значит — полезным.