Когда речь заходит об анализе временных рядов в Python, вездесущий pandas вызывает заслуженное уважение. Базовые возможности, такие как преобразование даты формата строки в datetime, или ресемплирование данных — уже почти рефлекс у каждого начинающего аналитика. Но сегодня я хочу показать вам кое-что посерьезнее. Pandas умеет гораздо больше, и это может по-настоящему сократить вам время и расширить горизонт возможностей.
Допустим, у нас есть DataFrame с погодными данными:
Первое, на что стоит обратить внимание — это метод
Но зачастую данные нужно агрегировать. Вот тут вступает
Вроде бы ничего нового. Но вы знали, что можно использовать нестандартные правила частоты? Например,
А теперь магия: скользящие окна. Метод
Обратите внимание: начиная с pandas 1.2 можно задавать окно в формате времени, не только в числах. Это даёт гибкость: окно “7 дней назад” будет учитывать фактические интервалы, а не просто 7 строк.
Идём глубже. Предположим, вы анализируете временной ряд с пропущенными значениями. В pandas есть умные способы заполнения:
Интерполяция по времени — гораздо лучше "затыкания дыр" средним. Она учитывает временные интервалы, что важно для равномерности.
А теперь маленький шедевр: работа с временными “offsets”. Например, мы хотим сдвинуть данные на два месяца вперёд:
Не просто сдвинуть по индексам — а сместить даты! Это особенно удобно при сравнении "текущих" и "прошлогодних" метрик.
Финальный штрих —
и
Эти методы облегчат задачу, когда нужно быстро вытащить записи только за рабочие часы или точно в полдень.
Pandas — не просто инструмент для таблиц. Это полноценный движок анализа данных по времени, скрывающий под капотом куда больше, чем кажется. Настройка частот, смещения, агрегирования, скользящие окна — всё это можно комбинировать для создания точных и наглядных аналитических инструментов. И в этом кроется сила.
Допустим, у нас есть DataFrame с погодными данными:
import pandas as pd
df = pd.read_csv('weather.csv', parse_dates=['timestamp'], index_col='timestamp')
Первое, на что стоит обратить внимание — это метод
.asfreq()
для смены частоты без усреднения. Например, если у нас почасовые данные, а мы хотим просто увидеть дневные “срезы”:daily_df = df.asfreq('D')
Но зачастую данные нужно агрегировать. Вот тут вступает
.resample()
— он похож на .groupby()
, но для времени:mean_temp_per_day = df['temperature'].resample('D').mean()
Вроде бы ничего нового. Но вы знали, что можно использовать нестандартные правила частоты? Например,
'W-MON'
даст недельную агрегацию с понедельника:weekly_data = df.resample('W-MON').agg({'temperature': 'max', 'humidity': 'mean'})
А теперь магия: скользящие окна. Метод
.rolling()
— это ваш билет в мир сглаживания и анализа трендов:df['temp_7d_avg'] = df['temperature'].rolling(window='7D').mean()
Обратите внимание: начиная с pandas 1.2 можно задавать окно в формате времени, не только в числах. Это даёт гибкость: окно “7 дней назад” будет учитывать фактические интервалы, а не просто 7 строк.
Идём глубже. Предположим, вы анализируете временной ряд с пропущенными значениями. В pandas есть умные способы заполнения:
df['temperature'] = df['temperature'].interpolate(method='time')
Интерполяция по времени — гораздо лучше "затыкания дыр" средним. Она учитывает временные интервалы, что важно для равномерности.
А теперь маленький шедевр: работа с временными “offsets”. Например, мы хотим сдвинуть данные на два месяца вперёд:
df_shifted = df.shift(periods=2, freq='M')
Не просто сдвинуть по индексам — а сместить даты! Это особенно удобно при сравнении "текущих" и "прошлогодних" метрик.
Финальный штрих —
.between_time()
и .at_time()
. Когда вы работаете с данными по минутам или часам и хотите анализировать, например, только дневное время активности:daytime_df = df.between_time('09:00', '18:00')
и
df_at_noon = df.at_time('12:00')
Эти методы облегчат задачу, когда нужно быстро вытащить записи только за рабочие часы или точно в полдень.
Pandas — не просто инструмент для таблиц. Это полноценный движок анализа данных по времени, скрывающий под капотом куда больше, чем кажется. Настройка частот, смещения, агрегирования, скользящие окна — всё это можно комбинировать для создания точных и наглядных аналитических инструментов. И в этом кроется сила.
Привет! Сегодня мы с вами разберем, как с помощью Python и мощного сетевого инструмента Scapy создать простое, но функциональное приложение для мониторинга сети. Этот инструмент стоит того, чтобы познакомиться с ним поближе: он позволяет захватывать, анализировать и даже генерировать сетевые пакеты. А главное — делать это в пару строк кода.
Что такое Scapy? Это библиотека, написанная на Python, которая дает полный контроль над сетевыми пакетами. Она позволяет легко писать собственные снифферы, сканеры и даже фреймы для тестирования безопасности. Нам же сегодня нужен сниффер — простой монитор сетевого трафика.
Устанавливается Scapy командой:
pip install scapy
Теперь перейдем к делу. Представим, что нам нужно создать программу, которая будет "слушать" наш сетевой интерфейс и выводить информацию о каждом проходящем TCP-пакете. Вот базовый пример:
from scapy.all import sniff, IP, TCP
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
ipsrc = packetIP.src
ipdst = packet[IP].dst
portsrc = packetTCP.sport
portdst = packet[TCP].dport
print(f"TCP Packet: {ipsrc}:{portsrc} -> {ipdst}:{portdst}")
sniff(filter="tcp", prn=processpacket, store=0)
Что здесь происходит:
- sniff — основная функция для захвата пакетов.
- filter="tcp" — захватываем только TCP-пакеты (можно задавать любой pcap-фильтр: например, "udp", "icmp", "port 80").
- prn=processpacket — указываем функцию, которая будет вызываться для каждого пакета.
- store=0 — не сохраняем пакеты в память, чтобы избежать утечек при длительной работе.
Функция processpacket проверяет, содержит ли пакет уровни IP и TCP, и если да — выводит адреса отправителя и получателя, а также порты.
А теперь немного улучшений. Допустим, мы хотим видеть только трафик HTTP. Вспомним, что стандартный порт HTTP — 80. Добавим проверку на это:
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
portdst = packetTCP.dport
if portdst == 80:
ipsrc = packetIP.src
ipdst = packet[IP].dst
print(f"HTTP request from {ipsrc} to {ipdst}")
Хотим ещё круче? Добавим логгирование в файл, чтобы потом можно было проанализировать происходящее:
import logging
logging.basicConfig(filename="netmon.log", level=logging.INFO)
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
ipsrc = packet[IP].src
ipdst = packetIP.dst
portsrc = packet[TCP].sport
portdst = packetTCP.dport
logentry = f"{ipsrc}:{portsrc} -> {ipdst}:{portdst}"
logging.info(logentry)
Так мы получаем файл netmon.log, в котором накапливается информация обо всех TCP-соединениях.
Scapy дает гораздо больше, чем просто мониторинг. Можно парсить DNS-запросы, определять операционные системы, делать ARP-сканы, захватывать пароли — всё это в пределах одной библиотеки.
Наш мониторинг пока базовый, но даёт отличную основу для развития: вы можете строить систему оповещений, графики активности или даже мини firewall. Главное — не забывайте, что захват трафика на чужих сетях без разрешения незаконен! Используйте Scapy с умом и по назначению.
На этом всё — до встречи в следующем посте!
Что такое Scapy? Это библиотека, написанная на Python, которая дает полный контроль над сетевыми пакетами. Она позволяет легко писать собственные снифферы, сканеры и даже фреймы для тестирования безопасности. Нам же сегодня нужен сниффер — простой монитор сетевого трафика.
Устанавливается Scapy командой:
pip install scapy
Теперь перейдем к делу. Представим, что нам нужно создать программу, которая будет "слушать" наш сетевой интерфейс и выводить информацию о каждом проходящем TCP-пакете. Вот базовый пример:
from scapy.all import sniff, IP, TCP
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
ipsrc = packetIP.src
ipdst = packet[IP].dst
portsrc = packetTCP.sport
portdst = packet[TCP].dport
print(f"TCP Packet: {ipsrc}:{portsrc} -> {ipdst}:{portdst}")
sniff(filter="tcp", prn=processpacket, store=0)
Что здесь происходит:
- sniff — основная функция для захвата пакетов.
- filter="tcp" — захватываем только TCP-пакеты (можно задавать любой pcap-фильтр: например, "udp", "icmp", "port 80").
- prn=processpacket — указываем функцию, которая будет вызываться для каждого пакета.
- store=0 — не сохраняем пакеты в память, чтобы избежать утечек при длительной работе.
Функция processpacket проверяет, содержит ли пакет уровни IP и TCP, и если да — выводит адреса отправителя и получателя, а также порты.
А теперь немного улучшений. Допустим, мы хотим видеть только трафик HTTP. Вспомним, что стандартный порт HTTP — 80. Добавим проверку на это:
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
portdst = packetTCP.dport
if portdst == 80:
ipsrc = packetIP.src
ipdst = packet[IP].dst
print(f"HTTP request from {ipsrc} to {ipdst}")
Хотим ещё круче? Добавим логгирование в файл, чтобы потом можно было проанализировать происходящее:
import logging
logging.basicConfig(filename="netmon.log", level=logging.INFO)
def processpacket(packet):
if packet.haslayer(IP) and packet.haslayer(TCP):
ipsrc = packet[IP].src
ipdst = packetIP.dst
portsrc = packet[TCP].sport
portdst = packetTCP.dport
logentry = f"{ipsrc}:{portsrc} -> {ipdst}:{portdst}"
logging.info(logentry)
Так мы получаем файл netmon.log, в котором накапливается информация обо всех TCP-соединениях.
Scapy дает гораздо больше, чем просто мониторинг. Можно парсить DNS-запросы, определять операционные системы, делать ARP-сканы, захватывать пароли — всё это в пределах одной библиотеки.
Наш мониторинг пока базовый, но даёт отличную основу для развития: вы можете строить систему оповещений, графики активности или даже мини firewall. Главное — не забывайте, что захват трафика на чужих сетях без разрешения незаконен! Используйте Scapy с умом и по назначению.
На этом всё — до встречи в следующем посте!
👍1
Python — язык, который поощряет чистоту, читаемость и элегантность. И одно из самых мощных проявлений этих качеств — конструкции контекстного менеджмента. Возможно, ты уже встречал волшебное слово with, но не совсем понимал, что именно происходит под капотом. Давай разберёмся.
Представим себе файл. Мы его открываем, читаем, а потом… забываем закрыть. Вроде бы ничего страшного — но если таких забытых файлов десятки, появляются утечки ресурсов. Контекстные менеджеры помогают гарантировать, что нужные действия будут выполнены автоматически, даже если в процессе произойдёт ошибка.
Базовый пример:
with open('data.txt', 'r') as file:
content = file.read()
После выхода из блока with Python сам вызовет file.close(). Удобно и безопасно.
Но фокус в том, что можно писать свои контекстные менеджеры! Чтобы понять, как это работает, вспомним о двух магических методах:
- enter()
- exit()
Создадим простой таймер:
import time
class Timer:
def enter(self):
self.start = time.time()
return self
def exit(self, exctype, excval, exctb):
self.end = time.time()
print(f'Time elapsed: {self.end - self.start:.4f} seconds')
Теперь используем:
with Timer():
total = sum(i**2 for i in range(1000000))
Контекст открылся, засеклось время. После выхода — замер завершился, результат выведен.
Но писать собственные классы с enter и exit — не всегда удобно. Тут приходит модуль contextlib. Он предлагает простой способ создавать менеджеры контекста из функций.
Пример с contextlib.contextmanager:
from contextlib import contextmanager
@contextmanager
def changedirectory(path):
import os
prevdir = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(prevdir)
Вот такой элегантный способ временно сменить директорию:
with changedirectory('/tmp'):
print('We are here:', os.getcwd())
После выхода — возвращаемся туда, откуда пришли. Даже если внутри блока произойдёт исключение.
А теперь чуть более продвинутый трюк: подавление ошибок. Модуль contextlib помогает снова:
from contextlib import suppress
with suppress(ZeroDivisionError):
print(1 / 0) # Ошибка будет проигнорирована
Очень полезно, когда есть неважные операции, которые могут не сработать, и их не хочется оборачивать в try/except.
И наконец: если ты работаешь с ресурсами — файлами, соединениями, блокировками — знай, что многие библиотеки уже поддерживают контекстные менеджеры. Например, threading.Lock:
import threading
lock = threading.Lock()
with lock:
# безопасный доступ к ресурсу
dosomething()
Безопасность, лаконичность, надёжность — вот за что мы любим with. Он делает код чище и устойчивее к ошибкам. А знание, как писать свои менеджеры контекста, открывает путь к по-настоящему выразительному Python-коду.
Представим себе файл. Мы его открываем, читаем, а потом… забываем закрыть. Вроде бы ничего страшного — но если таких забытых файлов десятки, появляются утечки ресурсов. Контекстные менеджеры помогают гарантировать, что нужные действия будут выполнены автоматически, даже если в процессе произойдёт ошибка.
Базовый пример:
with open('data.txt', 'r') as file:
content = file.read()
После выхода из блока with Python сам вызовет file.close(). Удобно и безопасно.
Но фокус в том, что можно писать свои контекстные менеджеры! Чтобы понять, как это работает, вспомним о двух магических методах:
- enter()
- exit()
Создадим простой таймер:
import time
class Timer:
def enter(self):
self.start = time.time()
return self
def exit(self, exctype, excval, exctb):
self.end = time.time()
print(f'Time elapsed: {self.end - self.start:.4f} seconds')
Теперь используем:
with Timer():
total = sum(i**2 for i in range(1000000))
Контекст открылся, засеклось время. После выхода — замер завершился, результат выведен.
Но писать собственные классы с enter и exit — не всегда удобно. Тут приходит модуль contextlib. Он предлагает простой способ создавать менеджеры контекста из функций.
Пример с contextlib.contextmanager:
from contextlib import contextmanager
@contextmanager
def changedirectory(path):
import os
prevdir = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(prevdir)
Вот такой элегантный способ временно сменить директорию:
with changedirectory('/tmp'):
print('We are here:', os.getcwd())
После выхода — возвращаемся туда, откуда пришли. Даже если внутри блока произойдёт исключение.
А теперь чуть более продвинутый трюк: подавление ошибок. Модуль contextlib помогает снова:
from contextlib import suppress
with suppress(ZeroDivisionError):
print(1 / 0) # Ошибка будет проигнорирована
Очень полезно, когда есть неважные операции, которые могут не сработать, и их не хочется оборачивать в try/except.
И наконец: если ты работаешь с ресурсами — файлами, соединениями, блокировками — знай, что многие библиотеки уже поддерживают контекстные менеджеры. Например, threading.Lock:
import threading
lock = threading.Lock()
with lock:
# безопасный доступ к ресурсу
dosomething()
Безопасность, лаконичность, надёжность — вот за что мы любим with. Он делает код чище и устойчивее к ошибкам. А знание, как писать свои менеджеры контекста, открывает путь к по-настоящему выразительному Python-коду.
Вы когда-нибудь задумывались, зачем использовать язык R, если у вас уже есть Python? Или наоборот? Казалось бы, оба отлично справляются с анализом данных. Но вот в чём соль: Python — это универсальный инструмент, бог с ним, швейцарский нож программиста. А R — это математика на стероидах. Его богатые статистические возможности делают его настоящим кладом для сложного анализа. В этом посте я расскажу, как объединить оба языка, чтобы выжать максимум из каждого.
🐍 + 📊 = ❤️
Для интеграции Python и R существует несколько способов, но самые удобные и популярные — это использование библиотек rpy2 и Jupyter с R-клетками через ipython-magic. Начнём с rpy2.
📦 Установка:
Убедитесь, что R установлен в вашей системе, затем:
pip install rpy2
Теперь магия:
from rpy2 import robjects
robjects.r('x <- rnorm(100)')
robjects.r('meanx <- mean(x)')
meanx = robjects.r('meanx')[0]
print("Mean from R:", meanx)
Здесь мы генерируем данные в стиле R, вычисляем среднее и забираем его обратно в Python. Очень удобно, когда у вас есть мощные R-пакеты вроде 'caret', 'forecast' или 'ggplot2', но вы хотите оборачивать их в пайтоновских скриптах.
Хочется смешивать код без лишнего бойлера? Тогда пришло время познакомиться с IPython magic-командой %%R. Установите R-кернел:
R
> install.packages("IRkernel")
> IRkernel::installspec()
Теперь в Jupyter:
%loadext rpy2.ipython
А в самой ячейке:
%%R
x <- rnorm(100)
print(summary(x))
Да-да, просто пишете R-код в Python-ноутбуке. Удобство в чистом виде.
🔁 Передача переменных
Обмен данными между языками возможен. Из Python в R:
import numpy as np
from rpy2.robjects import numpy2ri
numpy2ri.activate()
data = np.random.normal(size=100)
robjects.globalenv['x'] = data
robjects.r('summary(x)')
И обратно:
meanr = robjects.r('mean(x)')0
print(meanr)
📊 Дополнительный бонус — визуализация. Например, используйте ggplot2:
robjects.r('''
library(ggplot2)
df <- data.frame(x=rnorm(100), y=rnorm(100))
p <- ggplot(df, aes(x=x, y=y)) + geompoint()
print(p)
''')
Такой подход отлично подходит, если вы уже строите пайплайны в Python, а кто-то в команде держится за проверенные R-инструменты. Или вы просто хотите построить точный статистический анализ без костылей.
Итог: интеграция Python и R — это не борьба за первенство, а мощный симбиоз. Используйте Python для автоматизации и потоков, а R — для глубоких аналитических выкопок. Вместе они могут гораздо больше.
🐍 + 📊 = ❤️
Для интеграции Python и R существует несколько способов, но самые удобные и популярные — это использование библиотек rpy2 и Jupyter с R-клетками через ipython-magic. Начнём с rpy2.
📦 Установка:
Убедитесь, что R установлен в вашей системе, затем:
pip install rpy2
Теперь магия:
from rpy2 import robjects
robjects.r('x <- rnorm(100)')
robjects.r('meanx <- mean(x)')
meanx = robjects.r('meanx')[0]
print("Mean from R:", meanx)
Здесь мы генерируем данные в стиле R, вычисляем среднее и забираем его обратно в Python. Очень удобно, когда у вас есть мощные R-пакеты вроде 'caret', 'forecast' или 'ggplot2', но вы хотите оборачивать их в пайтоновских скриптах.
Хочется смешивать код без лишнего бойлера? Тогда пришло время познакомиться с IPython magic-командой %%R. Установите R-кернел:
R
> install.packages("IRkernel")
> IRkernel::installspec()
Теперь в Jupyter:
%loadext rpy2.ipython
А в самой ячейке:
%%R
x <- rnorm(100)
print(summary(x))
Да-да, просто пишете R-код в Python-ноутбуке. Удобство в чистом виде.
🔁 Передача переменных
Обмен данными между языками возможен. Из Python в R:
import numpy as np
from rpy2.robjects import numpy2ri
numpy2ri.activate()
data = np.random.normal(size=100)
robjects.globalenv['x'] = data
robjects.r('summary(x)')
И обратно:
meanr = robjects.r('mean(x)')0
print(meanr)
📊 Дополнительный бонус — визуализация. Например, используйте ggplot2:
robjects.r('''
library(ggplot2)
df <- data.frame(x=rnorm(100), y=rnorm(100))
p <- ggplot(df, aes(x=x, y=y)) + geompoint()
print(p)
''')
Такой подход отлично подходит, если вы уже строите пайплайны в Python, а кто-то в команде держится за проверенные R-инструменты. Или вы просто хотите построить точный статистический анализ без костылей.
Итог: интеграция Python и R — это не борьба за первенство, а мощный симбиоз. Используйте Python для автоматизации и потоков, а R — для глубоких аналитических выкопок. Вместе они могут гораздо больше.
Как разрабатывать 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