Python для начинающих
1.12K subscribers
346 photos
3 videos
232 files
64 links
Python для начинающих
Download Telegram
Привет, с вами Иван! Сегодня разберём интересную тему — как написать свой собственный лексический анализатор (lexer) на Python, используя модуль re. Это умение полезно, если вы хотите понять, как работают языки программирования изнутри или написать парсер для небольшого языка.

## Немного теории

Лексический анализатор — это инструмент, который разбивает текст на “токены”: числа, идентификаторы, слова, спецсимволы и т.д. Например, строку x = 5 + y лексер превращает в список токенов: имя, знак равно, число, плюс, имя.

Модуль re (regular expressions) делает этот процесс максимально простым и лаконичным.

## Делаем свой мини-лексер

Рассмотрим пример — напишем лексер для простых арифметических выражений (числа, знаки операций, скобки):

import re

# Описываем типы токенов и шаблоны для них
token_spec = [
("NUMBER", r'\d+(\.\d*)?'), # целое или дробное число
("IDENT", r'[A-Za-z_]\w*'), # идентификатор
("PLUS", r'\+'), # плюс
("MINUS", r'-'), # минус
("MULT", r'\*'), # умножение
("DIV", r'/'), # деление
("LPAREN", r'\('), # левая скобка
("RPAREN", r'\)'), # правая скобка
("SKIP", r'[ \t]+'), # пропускаем пробелы и табы
("MISMATCH", r'.'), # неизвестный символ — ошибка
]

token_regex = '|'.join(f'(?P<{name}>{pattern})' for name, pattern in token_spec)

def tokenize(code):
for match in re.finditer(token_regex, code):
kind = match.lastgroup
value = match.group()
if kind == "SKIP":
continue
elif kind == "MISMATCH":
raise RuntimeError(f"Unexpected character: {value}")
yield (kind, value)


Давайте проверим на практике:

expr = "a1 = 3.5 + (b2 - 7) * 4"
tokens = list(tokenize(expr))
print(tokens)


Результат:

[('IDENT', 'a1'), ('MISMATCH', '='), ('NUMBER', '3.5'), ('PLUS', '+'),
('LPAREN', '('), ('IDENT', 'b2'), ('MINUS', '-'), ('NUMBER', '7'),
('RPAREN', ')'), ('MULT', '*'), ('NUMBER', '4')]


## Как это работает?

- Для каждого токена задаём регулярное выражение.
- re.finditer проходит по всей строке, находя совпадения с шаблонами.
- Если токен — пробел или таб, пропускаем его. Если неизвестный символ — бросаем ошибку.

С помощью такой конструкции вы легко можете добавить новые типы токенов или немного сложнее изменить правила языка.

## Заключение

Создавать лексеры на Python просто — достаточно комбинировать немного re и креативности. Это отличный эксперимент для углубления знаний о языках и внутренних механизмах их работы!

На связи, Иван.
- Использование celery для отложенных задач и процессинга
Привет! Меня зовут Иван, и сегодня мы поговорим о настоящей магии асинхронных задач в Python — модуле Celery. Представьте, что ваш сайт отправляет письма пользователям или обрабатывает тяжелые отчёты. Если выполнять это прямо в запросе пользователя — он уснёт, дожидаясь ответа. А вот если передать дело “отложенному работнику” — всё становится куда быстрее. Именно таким работником и выступает Celery.

## Кратко: что такое Celery?

Celery — это распределённый исполнитель задач, написанный на Python. Он позволяет запускать любые функции в фоне, не блокируя основной поток программы. Для работы ему потребуется брокер сообщений, например, Redis или RabbitMQ — через них Celery отправляет задачи своим воркерам.

## Первый пример — отправка письма

Давайте рассмотрим простой пример. Сначала установим необходимые пакеты:

pip install celery redis


Создадим файл tasks.py:

from celery import Celery

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

@app.task
def send_welcome_email(user_email):
print(f"Sending welcome email to {user_email}")
# тут могла бы быть интеграция с реальной email-системой


Теперь можно вызвать задачу асинхронно:

# main.py
from tasks import send_welcome_email

send_welcome_email.delay('newuser@example.com')


Функция delay — и есть магия: она “отправляет” задачу воркеру Celery, а не запускает её прямо сейчас.

## Второй пример — продолжительный процессинг

Что делать, если вам надо обработать много данных, например, генерировать PDF-отчёты? Запускаем это тоже через Celery!

@app.task
def generate_report(report_id):
print(f"Generating report {report_id}...")
# Симуляция долгой работы
import time
time.sleep(5)
print(f"Report {report_id} is ready!")


Теперь задача “варится” в фоне, не мешая пользователям сайта.

## Почему Celery популярен?

- Гибкость: задачи могут быть очередями с разными приоритетами.
- Масштабируемость: запускайте хоть сотню воркеров — всё заработает.
- Мониторинг: Celery легко интегрируется с Flower — инструментом визуального контроля за задачами.

Celery — идеальный выбор, если быстрые фокусы уже не спасают, а задачи требуются “класть на потом”. Попробуйте применить его в своих проектах — и код задышит полной грудью!
👍1
- Введение в веб-ботов с протоколом WebSocket и Python
Привет! С вами Иван, и сегодня мы окунемся в магию живых, мгновенных соединений с помощью WebSocket и Python.

Когда слышишь слово “бот”, сразу представляешь автоматизацию рутины: рассылки, ответы, акции. Но большинство таких ботов работает с HTTP-запросами — обычными односторонними сообщениями. А что если нужен живой диалог, например, чат-бот или отслеживание биржевых цен в режиме реального времени? Вот тут и появляется герой сегодняшнего выпуска — протокол WebSocket!

WebSocket — это двустороннее соединение: клиент и сервер могут отправлять данные друг другу как только захотят. И Python готов работать с этим напрямую через библиотеку websockets.

### Первый пример: клиент на WebSocket

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

import asyncio
import websockets

async def listen():
uri = "ws://localhost:8765"
async with websockets.connect(uri) as websocket:
while True:
message = await websocket.recv()
print(f"Received: {message}")

asyncio.run(listen())


Всего несколько строк — и вы уже получаете данные в реальном времени!

### Второй пример: сервер WebSocket на Python

Запустить свой сервер тоже просто:

import asyncio
import random
import websockets

async def send_random(websocket):
while True:
number = random.randint(1, 100)
await websocket.send(str(number))
await asyncio.sleep(1)

async def main():
async with websockets.serve(send_random, "localhost", 8765):
await asyncio.Future() # run forever

asyncio.run(main())


Этот сервер будет каждую секунду отдавать случайное число всем подключившимся.

### Идеи для ботов

С помощью WebSocket вы можете сделать:
- чат-бота, который отвечает мгновенно, реагируя на каждое сообщение;
- сборщика уведомлений из разных систем в одном месте;
- монитор трейдов и бирж, чтобы получать апдейты моментально.

Используйте WebSocket для ускорения реакции в своих Python-проектах — этот протокол буквально открывает двери в мир мгновенного обмена данными.
👍1
- Секреты эффективной работы с модулями shutil и os
Привет, на связи Иван! Сегодня расскажу о двух хитрых помощниках Python — модулях shutil и os, которые превращают скучную работу с файлами и папками в настоящее шоу. Узнаем, как быстро манипулировать файлами, автоматизировать рутину и не бояться "переезда" данных.

### Модуль os: база для маневров

Модуль os — это как швейцарский нож для работы с файловой системой. С его помощью можно узнать, какие файлы лежат в папке, создать каталоги и даже выяснить, в какой именно папке сейчас "живет" скрипт.

import os

current_dir = os.getcwd() # Текущая рабочая директория
files = os.listdir(current_dir) # Список файлов в папке
os.mkdir('new_folder') # Создаём новую папку
os.rename('file.txt', 'renamed_file.txt') # Переименование файла


Секрет №1: всегда проверяйте существование файлов и папок перед операциями! Это спасёт от ненужных ошибок.

if not os.path.exists('new_folder'):
os.mkdir('new_folder')


### Модуль shutil: мастер “телепортации” данных

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

import shutil

shutil.copy('data.txt', 'backup/data.txt') # Копируем файл
shutil.move('backup/data.txt', 'archive/data.txt') # Перемещаем файл
shutil.rmtree('archive') # Удаляем целую папку cо всеми файлами!


Секрет №2: Используйте shutil.copytree() для копирования целых каталогов, а ещё — можно фильтровать, какие файлы копировать!

def ignore_txt_files(dir, files):
return [f for f in files if f.endswith('.txt')]

shutil.copytree('original', 'copy', ignore=ignore_txt_files)


### Combo: автоматизация на максимум

Комбинируя os и shutil, можно создать свои файловые менеджеры или скрипты для бэкапа. Например, копировать все файлы с определённым расширением:

import os
import shutil

for filename in os.listdir('docs'):
if filename.endswith('.pdf'):
shutil.copy(os.path.join('docs', filename), 'pdf_backup')


### Итог

shutil и os — тандем для любой работы с файлами и папками. Запомните ключевые методы, всегда проверяйте операции на существование объектов и пробуйте писать автоматизации под себя! Всегда рад делиться секретами продуктивной работы на Python — до новых встреч, ваш Иван.
👍1
- Как использовать модуль mmap для оптимизации ввода-вывода
Привет! С вами Иван и сегодня поговорим о настоящей магии — модуле mmap в Python. Все мы привыкли работать с файлами по-старинке: открыли, прочитали в память, закрыли. Но что если файл огромный, а нам нужно обработать только его часть? Пожалуй, тут на сцену выходит герой дня — mmap.

## Что такое mmap и зачем он нужен?

mmap позволяет отображать файл в память и работать с ним как с обычным массивом байтов. Это особенно круто при работе с большими файлами, когда нет смысла тратить память на всё содержимое сразу. Всё, что тебе нужно — доступно по байтовому адресу!

## Пример 1: Чтение кусочка огромного файла

Допустим, у нас есть гигантский лог-файл, а мы хотим прочитать только первые 100 байт.

import mmap

with open('huge.log', 'rb') as f:
with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as mm:
snippet = mm[:100]
print(snippet.decode('utf-8', errors='ignore'))


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

## Пример 2: Поиск без загрузки файла

А если нужен поиск по файлу? Смотри, как просто ищется подстрока:

import mmap

search_phrase = b'ERROR'

with open('huge.log', 'rb') as f:
with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as mm:
pos = mm.find(search_phrase)
if pos != -1:
print(f'Found at position {pos}')


Как в строке, только по файлу, и всё ― без лишней траты памяти.

## Пример 3: Редактирование файла на месте

mmap позволяет даже изменять файлы на лету. Например, заменить первые 5 байт на другие:

import mmap

with open('data.bin', 'r+b') as f:
with mmap.mmap(f.fileno(), length=0) as mm:
mm[0:5] = b'HELLO'


Изменения сразу отражаются в файле!

## Итог

mmap станет отличным подспорьем, если вы хотите ускорить работу с файлами, не жертвуя оперативной памятью. Работать с файлами становится действительно удобно ― вы просто манипулируете данными как с массивом, и всё прозрачно сохраняется на диск. Обязательно попробуйте в своих проектах!

— Иван, ваш проводник в мир эффективного Python
👍1
- Основы синтаксического анализа и построения деревьев с lxml
Привет! На связи Иван, и сегодня разберём один из мощных инструментов для работы с XML и HTML — библиотеку lxml. Если вы когда-либо сталкивались с необходимостью "разобрать" XML-файл или вытянуть кусочек информации из HTML, lxml сделает это за считанные строки кода. Давайте посмотрим, как работает синтаксический анализ и построение деревьев с этим модулем на практике.

## Загрузка и структура XML

Для начала представим классический XML:

<data>
<user id="1">
<name>John</name>
<age>30</age>
</user>
<user id="2">
<name>Ann</name>
<age>25</age>
</user>
</data>


С помощью lxml превратить этот текст в дерево проще простого:

from lxml import etree

xml_text = '''
<data>
<user id="1">
<name>John</name>
<age>30</age>
</user>
<user id="2">
<name>Ann</name>
<age>25</age>
</user>
</data>
'''

root = etree.fromstring(xml_text)


Теперь root — вершина дерева, а каждый "user" — его потомок. Посмотреть, кто есть кто:

for user in root.findall("user"):
print(user.get("id"), user.findtext("name"))


Вывод будет:
1 John  
2 Ann


## Парсинг HTML и XPath

Работает lxml и с HTML! Очень удобно, если нужно вытащить ссылки или заголовки со странички.

from lxml import html

html_text = '''
<html>
<body>
<h2>Cool title</h2>
<a href="https://example.com">Read more</a>
</body>
</html>
'''

tree = html.fromstring(html_text)
link = tree.xpath('//a/@href')[0]
title = tree.xpath('//h2/text()')[0]
print(title, link)


## Зачем всё это?

lxml крут тем, что строит дерево элементов: вы можете свободно перемещаться по структуре, менять значения, добавлять или удалять узлы. XPath — как навигация по дереву на стероидах: за одну строку можно вытянуть вообще всё, что душе угодно.

В результате: lxml незаменим, когда появляется задача парсить XML или HTML, вытаскивать данные, модифицировать структуру, или даже генерировать новые файлы. Всего три-четыре строки кода — и у вас весь документ, как на ладони.
- Как безопасно работать с конфиденциальными данными в Python
Привет! С вами Иван, и сегодня хочу поговорить о том, как работать с конфиденциальными данными в Python и не дать утечкам информации сломать вам карьеру (или, не дай бог, жизнь).

Работая с конфиденциальной информацией — паролями, токенами, API-ключами, персональными данными — нельзя слепо полагаться на "авось пронесёт". Давайте пройдёмся по базовым, жизненно необходимым приемам защиты данных на практике.

1. Не храните секреты в коде

Каждый видел примеры вроде:
password = "SuperSecret123"

Это антипаттерн! Любой, у кого есть доступ к коду, увидит ваш пароль. Используйте переменные окружения:

import os

password = os.getenv("DB_PASSWORD")


Храните настоящие значения в файле .env и никогда не загружайте его в git-репозиторий.

2. Используйте dotenv для удобства

Модуль python-dotenv поможет легко считывать переменные окружения из файла. Просто создайте .env-файл:

DB_PASSWORD=SuperSecret123


И загрузите их:

from dotenv import load_dotenv
import os

load_dotenv()
password = os.getenv("DB_PASSWORD")


3. Никогда не логируйте чувствительные данные

Если вы ведёте логи, не заносите в них пароли, токены, номера карт. Используйте параметр mask в логах своего приложения или самостоятельно следите, что именно выводит ваш print/logging:

import logging

logging.info("User logged in") # А вот такого - избегайте: logging.info(f"Password: {password}")


4. Шифруйте данные на диске и в передаче

Для простого симметричного шифрования идеально подходит модуль cryptography:

from cryptography.fernet import Fernet

key = Fernet.generate_key()
f = Fernet(key)

token = f.encrypt(b"My secret data")
print(token)
print(f.decrypt(token))


Храните ключ отдельно от самого приложения!

5. Не забывайте про права доступа

Соблюдайте принцип наименьших привилегий — не давайте скриптам больше полномочий, чем нужно. И не храните лишние данные без необходимости.

Вывод:
Работа с конфиденциальной информацией – это не только про модные фреймворки, но и про вашу репутацию. Грамотно подходите к вопросам хранения и передачи секретов, а Python и пара библиотек вам в этом помогут.
👍1
- Введение в генераторы AST (Abstract Syntax Tree) в Python
Привет! С вами Иван, и сегодня у нас одна из самых необычных тем — погружение в мир AST (Abstract Syntax Tree) в Python. Если ты когда-нибудь мечтал покопаться под капотом языка, узнать, как Python понимает твой код перед исполнением — добро пожаловать!

### Что такое AST?

AST — это "абстрактное синтаксическое дерево". Представь себе: любой Python-код сначала превращается в дерево объектов, которое структурирует код на уровни — функции, выражения, операторы, значения. Работа с AST похожа на анализ ДНК программы: ты можешь видеть, из чего состоит твой код, а иногда — даже переписать его на лету!

### Где это пригодится?

- Статический анализ кода (например, поиск ошибок или автоматическая проверка стиля)
- Автоматическая генерация кода
- Рефакторинг

### Модуль ast — твой вход в AST

Python предлагает встроенный модуль ast, который позволяет парсить исходный код и получать AST-дерево, исследовать его и даже модифицировать.

#### Пример 1: Парсим простую функцию

import ast

source_code = """
def greet(name):
return "Hello, " + name
"""

tree = ast.parse(source_code)
print(ast.dump(tree, indent=4))

Этот код превратит функцию greet в красивое дерево с вложенными нодами: FunctionDef, arguments, Return и т.д.

#### Пример 2: Ищем все вызовы функций

Хотим найти все места, где вызываются функции? (Call-ноды)

class CallVisitor(ast.NodeVisitor):
def visit_Call(self, node):
print("Function call found:", ast.dump(node))
self.generic_visit(node)

tree = ast.parse("""
result = add(x, y)
print(result)
""")
CallVisitor().visit(tree)


#### Пример 3: Модификация кода на лету

Пусть теперь программа заменяет все числа 42 на 100:

class ReplaceNumber(ast.NodeTransformer):
def visit_Constant(self, node):
if isinstance(node.value, int) and node.value == 42:
return ast.Constant(value=100)
return node

code = "answer = 42"
tree = ast.parse(code)
tree = ReplaceNumber().visit(tree)
exec(compile(tree, filename="<ast>", mode="exec"))
print(answer) # Выведет 100


---

Используя AST, ты перестаешь быть просто пользователем языка — ты становишься его архитектором! Это мощный инструмент не только для изучения Python, но и для создания собственных инструментов для анализа и трансформации кода. Попробуй — и ты посмотришь на свой код другими глазами!
👍1
- Использование библиотеки zbar для обработки QR-кодов
Привет, друзья! Меня зовут Иван, и сегодня я расскажу о библиотеке, которая превратит ваш Python-скрипт в детектор QR-кодов — встречайте, zbar!

Зачем вообще обрабатывать QR-коды в Python? Казалось бы, приложения на смартфоне всё делают за нас. Но представьте: у вас огромная база изображений, где зашифрованы купоны, анкеты, ключи доступа… Не будешь же ты все их сканировать вручную! Вот тут и вступает в игру zbar: быстрый, минималистичный и лёгкий инструмент для сканирования штрих- и QR-кодов прямо в ваших сценариях.

Начнём с установки. Если у вас Linux, скорее всего, zbar уже можно поставить через пакетный менеджер, например:
sudo apt-get install libzbar0
pip install pyzbar

В Windows достаточно pip install pyzbar.

Первый пример: минимализм во плоти
Сканировать QR-код из изображения с помощью Python проще простого:

from pyzbar.pyzbar import decode
from PIL import Image

img = Image.open('qrcode_example.png')
decoded = decode(img)
for obj in decoded:
print("Type:", obj.type)
print("Data:", obj.data.decode('utf-8'))


Вот и всё! Код первым же вызовом вернёт вам содержимое QR-кода. Хотите прочитать несколько кодов на одном изображении — не проблема, цикл их вам покажет.

Читаем QR-коды c веб-камеры
Если у вас есть камера и библиотека OpenCV, можно ловить QR-коды в реальном времени:

import cv2
from pyzbar.pyzbar import decode

cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
for code in decode(frame):
text = code.data.decode('utf-8')
print("Found QR:", text)
cv2.imshow('QR reader', frame)
if cv2.waitKey(1) == 27: # Esc для выхода
break
cap.release()
cv2.destroyAllWindows()


Совет: кодировка часто бывает UTF-8, но лучше прописывать явно при декодировании. Zbar умеет находить и EAN, и CODE128, и DataMatrix — вдруг вам понадобится не только QR?

Используйте zbar для автоматизации, распознавания купонов, генерации ссылок, билетов или входных ключей! Открывается целый мир автоматической обработки данных, а сам код всегда предельно лаконичен.

Пробуйте, экспериментируйте и решайте задачи с минимальными усилиями!
Ваша «магия» начинается с нескольких строк — а творить уже можно что угодно.
На связи, Иван.
- Как внедрить отзывчивый дизайн в Django с использованием Django Crispy Forms
- Как внедрить отзывчивый дизайн в Django с использованием Django Crispy Forms
Привет! На связи Иван, и сегодня я расскажу, как сделать формы Django не только красивыми, но и отзывчивыми с помощью Django Crispy Forms. Если ты когда-либо создавал формы в Django, то знаешь, какими унылыми они выглядят по умолчанию. А хочется ведь, чтобы всё было “вау”! Вот тут и приходит на помощь “хрустящий” модуль.

Что такое Django Crispy Forms?

Crispy Forms — сверхполезное расширение для Django, чтобы быстро (и, главное, легко) внедрять адаптивные и красивые формы. Оно отлично дружит с Bootstrap — популярнейшим CSS-фреймворком для отзывчивого дизайна.

Установка

Сначала, конечно, устанавливаем сам crispyforms и Bootstrap, если его ещё нет:

```bash
pip install django-crispy-forms
pip install crispy-bootstrap5 # последняя версия Bootstrap
```

Затем добавляем в `settings.py`:

```python
INSTALLED
APPS =
...
"crispy_forms",
"crispy_bootstrap5",


CRISPYALLOWEDTEMPLATEPACKS = "bootstrap5"
CRISPY
TEMPLATEPACK = "bootstrap5"
```

**Использование: магия в действии**

Стандартная форма в Django:

```python
from django import forms

class ContactForm(forms.Form):
name = forms.CharField(max
length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)

Чтобы сделать её «хрустящей» и отзывчивой, используем Crispy Forms в шаблоне:

django
{% load crispyformstags %}
<form method="post">
{% csrftoken %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Send</button>
</form>
```

Благодаря фильтру `crispy`, поля автоматически получают классы Bootstrap, а сама форма становится адаптивной!

**Совет:** чтобы кастомизировать расположение полей или добавить дополнительные визуальные элементы, воспользуйся Layout из crispy
forms:

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Submit

class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Row(
Column('name', css_class='form-group col-md-6 mb-0'),
Column('email', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'message',
Submit('submit', 'Send')
)


Теперь форма распределяется по двум колонкам на широкой странице — динамично и удобно для пользователя!

Вывод

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

До встречи в следующей статье!
👍1