Модуль
Если вы всё ещё склеиваете пути к файлам через
---
### Зачем нужен
- Не нужно думать о слэше:
- Пути становятся объектами, а не строками.
- Методы для чтения/записи файлов встроены прямо в объект пути.
Подключение модуля:
---
### Создание и комбинирование путей
Оператор
---
### Поиск файлов по маске
Найдем все
---
### Чтение и запись файлов
Необязательно открывать файл через
Есть и бинарные варианты:
---
### Создание директорий и безопасная работа
---
### Абсолютные пути и нормализация
---
pathlib: современная работа с файловой системойЕсли вы всё ещё склеиваете пути к файлам через
os.path и плюсики — самое время познакомиться с pathlib. Это «современный» способ работы с путями в Python: объектно-ориентированный, удобный и кроссплатформенный.---
### Зачем нужен
pathlibpathlib решает несколько болезненных мест:- Не нужно думать о слэше:
/ под Linux и \ под Windows. - Пути становятся объектами, а не строками.
- Методы для чтения/записи файлов встроены прямо в объект пути.
Подключение модуля:
from pathlib import Path
---
### Создание и комбинирование путей
from pathlib import Path
base_dir = Path.home() # Домашняя папка пользователя
project_dir = base_dir / "my_project" / "data" # Склеивание через /
print(project_dir)
print(project_dir.exists()) # Проверяем, существует ли путь
print(project_dir.is_dir()) # Это папка?
Оператор
/ перегружен и безопасно соединяет части пути с учётом ОС.---
### Поиск файлов по маске
Найдем все
.txt в директории:data_dir = Path("data")
for txt_file in data_dir.glob("*.txt"):
print(txt_file.name, txt_file.stat().st_size, "bytes")
glob() поддерживает маски (*, **) и позволяет быстро обходить дерево каталогов.---
### Чтение и запись файлов
Необязательно открывать файл через
open:file_path = Path("data") / "notes.txt"
# Запись текста
file_path.write_text("Hello, pathlib!\nSecond line.")
# Чтение текста
content = file_path.read_text()
print(content)
Есть и бинарные варианты:
write_bytes() и read_bytes().---
### Создание директорий и безопасная работа
logs_dir = Path("logs")
logs_dir.mkdir(exist_ok=True, parents=True) # Создаст все недостающие папки
log_file = logs_dir / "app.log"
if not log_file.exists():
log_file.write_text("Log start\n")
else:
with log_file.open("a", encoding="utf-8") as f:
f.write("New log line\n")
parents=True создаст всю цепочку директорий, а exist_ok=True не вызовет ошибку, если папка уже есть.---
### Абсолютные пути и нормализация
p = Path("data") / ".." / "data" / "file.txt"
print(p) # Относительный "кривой" путь
print(p.resolve()) # Нормализованный абсолютный путь
resolve() приводит путь к каноничному виду и показывает, куда он реально ведет.---
pathlib хорошо ложится на мышление «объект пути + действия с ним», избавляя от ручной возни со строками. Если вы начинаете с Python сегодня — имеет смысл сразу привыкать именно к такому стилю работы с файловой системой.👍3
Как использовать модуль
Когда вы считаете средние оценки, анализируете продажи или смотрите на результаты эксперимента — без базовой статистики далеко не уедешь. В Python для этого есть готовый инструмент — модуль
---
## Подготовка
Модуль встроен в стандартную библиотеку, поэтому никаких установок не нужно:
Для примеров возьмём список чисел:
---
## Среднее (mean)
Среднее арифметическое — сумма всех значений, делённая на их количество. В
Круто то, что модуль сам обрабатывает
---
## Медиана (median)
Медиана — это «середина» отсортированных данных. Она устойчивее к выбросам. Если в выборке внезапно появится «сумасшедшее» значение, среднее уедет, а медиана — почти нет.
Медиана сразу показывает, что «нормальные» значения всё ещё где-то около 12–13, а не 258.75.
---
## Мода (mode)
Мода — самое часто встречающееся значение. Полезно, когда нужно найти «типичный» элемент: самый популярный рейтинг, любимый номер, частый результат.
Важно: если в данных несколько значений с одинаковой максимальной частотой,
---
## Быстрый мини-анализ набора данных
Соберём всё вместе:
Всего несколько строк — и вы уже видите «портрет» своих данных: где центр, где разброс и какое значение встречается чаще всего.
Модуль
statistics: среднее, медиана и мода без боли в мозгеКогда вы считаете средние оценки, анализируете продажи или смотрите на результаты эксперимента — без базовой статистики далеко не уедешь. В Python для этого есть готовый инструмент — модуль
statistics. Он избавляет от самописных циклов и формул и помогает считать всё в одну строку.---
## Подготовка
Модуль встроен в стандартную библиотеку, поэтому никаких установок не нужно:
import statistics as stats
Для примеров возьмём список чисел:
data = [10, 12, 13, 15, 15, 17, 18]
---
## Среднее (mean)
Среднее арифметическое — сумма всех значений, делённая на их количество. В
statistics это делается так:import statistics as stats
data = [10, 12, 13, 15, 15, 17, 18]
avg = stats.mean(data)
print(avg) # 14.285714285714286
Круто то, что модуль сам обрабатывает
int и float, не нужно думать о типах.---
## Медиана (median)
Медиана — это «середина» отсортированных данных. Она устойчивее к выбросам. Если в выборке внезапно появится «сумасшедшее» значение, среднее уедет, а медиана — почти нет.
import statistics as stats
data = [10, 12, 13, 1000] # явный выброс
mean_value = stats.mean(data)
median_value = stats.median(data)
print(mean_value) # 258.75
print(median_value) # 12.5
Медиана сразу показывает, что «нормальные» значения всё ещё где-то около 12–13, а не 258.75.
---
## Мода (mode)
Мода — самое часто встречающееся значение. Полезно, когда нужно найти «типичный» элемент: самый популярный рейтинг, любимый номер, частый результат.
import statistics as stats
grades = [5, 4, 5, 3, 4, 5, 5, 4]
most_common = stats.mode(grades)
print(most_common) # 5
Важно: если в данных несколько значений с одинаковой максимальной частотой,
mode() в некоторых версиях Python может выбросить StatisticsError. Для таких случаев есть более гибкая функция multimode():import statistics as stats
values = [1, 2, 2, 3, 3]
modes = stats.multimode(values)
print(modes) # [2, 3]
---
## Быстрый мини-анализ набора данных
Соберём всё вместе:
import statistics as stats
data = [12, 15, 17, 15, 19, 21, 15, 18]
summary = {
"mean": stats.mean(data),
"median": stats.median(data),
"mode": stats.mode(data),
"min": min(data),
"max": max(data)
}
print(summary)
# Пример вывода:
# {'mean': 16.5, 'median': 16.0, 'mode': 15, 'min': 12, 'max': 21}
Всего несколько строк — и вы уже видите «портрет» своих данных: где центр, где разброс и какое значение встречается чаще всего.
Модуль
statistics — отличный первый шаг в сторону анализа данных, без pandas и сложной математики. Идеален для учебных задач, прототипов и маленьких утилит.👍3
### Создание простого HTTP‑клиента с помощью
Большинство начинающих знакомятся с веб‑запросами через библиотеку
---
## Первый запрос: GET к публичному API
Сделаем простой GET‑запрос к публичному API и разберём шаги.
Что тут важно:
-
-
-
-
---
## Отправка данных: простой POST
Теперь отправим JSON‑данные методом POST. Здесь уже нужны заголовки и тело запроса:
Ключевые моменты:
- Тело запроса мы сериализуем через
- Обязательно указываем
-
---
## Обработка ошибок и таймаут
Реальный клиент должен быть готов к сетевым ошибкам:
Тут:
-
- исключения
---
Зная
http.clientБольшинство начинающих знакомятся с веб‑запросами через библиотеку
requests. Удобно, но иногда полезно заглянуть на «низкий уровень» и понять, как все работает внутри. Для этого в стандартной библиотеке Python есть модуль http.client.---
## Первый запрос: GET к публичному API
Сделаем простой GET‑запрос к публичному API и разберём шаги.
import http.client
import json
conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com")
conn.request("GET", "/posts/1")
response = conn.getresponse()
print("Status:", response.status, response.reason)
data = response.read()
text = data.decode("utf-8")
post = json.loads(text)
print("Title:", post["title"])
conn.close()
Что тут важно:
-
HTTPSConnection — шифрованное соединение (для http:// был бы HTTPConnection);-
request(method, url, body=None, headers={}) — отправка запроса;-
getresponse() — получение объекта ответа;-
read() — сырые байты, которые обычно нужно декодировать (decode) и парсить (JSON, HTML и т.д.).---
## Отправка данных: простой POST
Теперь отправим JSON‑данные методом POST. Здесь уже нужны заголовки и тело запроса:
import http.client
import json
conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com")
payload = {"title": "foo", "body": "bar", "userId": 1}
body = json.dumps(payload)
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
conn.request("POST", "/posts", body=body, headers=headers)
response = conn.getresponse()
print("Status:", response.status)
print("Headers:", dict(response.getheaders()))
data = response.read().decode("utf-8")
created_post = json.loads(data)
print("Created ID:", created_post["id"])
conn.close()
Ключевые моменты:
- Тело запроса мы сериализуем через
json.dumps;- Обязательно указываем
Content-Type;-
getheaders() возвращает список пар заголовков.---
## Обработка ошибок и таймаут
Реальный клиент должен быть готов к сетевым ошибкам:
import http.client
import socket
try:
conn = http.client.HTTPSConnection("example.com", timeout=3)
conn.request("GET", "/")
response = conn.getresponse()
print("Status:", response.status)
conn.close()
except (http.client.HTTPException, socket.timeout) as exc:
print("Request failed:", exc)
Тут:
-
timeout защищает от «вечного ожидания»;- исключения
HTTPException и socket.timeout помогают корректно отреагировать на проблемы сети.---
Зная
http.client, легче понимать, что делает любая высокоуровневая библиотека: устанавливает соединение, формирует запрос, отправляет тело, читает статус, заголовки и содержимое. Это отличный шаг к более глубокому пониманию сетевого кода в Python.👍1
### Изучаем
Если вы хоть раз вручную писали вложенные циклы, чтобы перебрать все пары, тройки или варианты, — модуль
---
## Комбинации: выбираем без повторов
Комбинация — это выбор элементов без учета порядка. Из
- не повторяет элементы;
-
- всё генерируется лениво (по мере запроса).
Полезно, когда перебираете возможные команды, наборы опций или подсеты признаков в задаче машинного обучения.
---
## Комбинации с повторениями
Иногда элемент можно брать несколько раз: монеты, кубики, вкусы мороженого.
---
## Декартово произведение: все возможные варианты
Результат:
-
-
-
- и т.д.
Можно задать повторения:
Это уже все возможные броски двух кубиков.
---
## Комбинации против продукта: что когда использовать?
- Нужен выбор из одного набора без повторов →
- Нужен выбор из одного набора с возможными повторами →
- Нужны все сочетания из нескольких наборов →
- Хотите сымитировать несколько одинаковых наборов (кубики, пароли фиксированной длины) →
---
itertools: комбинации и декартовы произведенияЕсли вы хоть раз вручную писали вложенные циклы, чтобы перебрать все пары, тройки или варианты, — модуль
itertools создан для вас. Он умеет генерировать комбинации и продукты «на лету», не занимая лишнюю память.---
## Комбинации: выбираем без повторов
Комбинация — это выбор элементов без учета порядка. Из
[1, 2, 3] пары такие: (1, 2), (1, 3), (2, 3).from itertools import combinations
items = ['a', 'b', 'c', 'd']
for pair in combinations(items, 2):
print(pair)
combinations(iterable, r):- не повторяет элементы;
-
(a, b) и (b, a) считаются одним вариантом;- всё генерируется лениво (по мере запроса).
Полезно, когда перебираете возможные команды, наборы опций или подсеты признаков в задаче машинного обучения.
---
## Комбинации с повторениями
Иногда элемент можно брать несколько раз: монеты, кубики, вкусы мороженого.
from itertools import combinations_with_replacement
flavors = ['vanilla', 'chocolate', 'strawberry']
for combo in combinations_with_replacement(flavors, 2):
print(combo)
('vanilla', 'vanilla') здесь вполне допустим.---
## Декартово произведение: все возможные варианты
product — это как вложенные циклы, только в одну строку. Идеален для генерации всех комбинаций параметров.from itertools import product
sizes = ['S', 'M', 'L']
colors = ['black', 'white']
for item in product(sizes, colors):
print(item)
Результат:
-
('S', 'black')-
('S', 'white')-
('M', 'black')- и т.д.
Можно задать повторения:
for roll in product(range(1, 7), repeat=2):
print(roll)
Это уже все возможные броски двух кубиков.
---
## Комбинации против продукта: что когда использовать?
- Нужен выбор из одного набора без повторов →
combinations- Нужен выбор из одного набора с возможными повторами →
combinations_with_replacement- Нужны все сочетания из нескольких наборов →
product- Хотите сымитировать несколько одинаковых наборов (кубики, пароли фиксированной длины) →
product(..., repeat=n)---
itertools экономит память и время разработки: вы получаете мощный генератор вариантов без километров вложенных циклов. Как только ловите себя на мысли «сейчас напишу ещё один for внутри for», сначала загляните в этот модуль.👍4
Модуль
Когда нужно что-то «уникальное» — многие программисты тянутся к времени, счётчикам или даже случайным числам. Проблема в том, что всё это легко пересекается, особенно в распределённых системах. Здесь в игру вступает модуль
UUID (Universally Unique Identifier) — это 128-битное число, обычно записываемое как строка вроде:
Вероятность коллизии настолько мала, что их смело используют в базах данных, API, токенах и временных файлах.
---
### Базовая генерация UUID
---
### Разные версии UUID
Модуль поддерживает несколько схем:
Где это полезно:
-
-
-
---
### UUID как строки и обратно
Чаще всего UUID хранят как строки (например, в базе):
Можно работать и с байтами:
---
### Практический мини-пример: генерация ключей для API
Метод
---
Модуль
uuid: генерация уникальных идентификаторов без боли и коллизийКогда нужно что-то «уникальное» — многие программисты тянутся к времени, счётчикам или даже случайным числам. Проблема в том, что всё это легко пересекается, особенно в распределённых системах. Здесь в игру вступает модуль
uuid — стандартный способ генерировать уникальные идентификаторы в Python.UUID (Universally Unique Identifier) — это 128-битное число, обычно записываемое как строка вроде:
550e8400-e29b-41d4-a716-446655440000Вероятность коллизии настолько мала, что их смело используют в базах данных, API, токенах и временных файлах.
---
### Базовая генерация UUID
import uuid
user_id = uuid.uuid4()
print(user_id) # например: 3e7c0e78-9a8e-4b52-9780-4e1c23f57abc
print(type(user_id)) # <class 'uuid.UUID'>
uuid4() генерирует UUID на основе криптографически стойкого генератора случайных чисел. Это самый популярный вариант.---
### Разные версии UUID
Модуль поддерживает несколько схем:
import uuid
# v1 — на основе MAC-адреса и времени
session_id = uuid.uuid1()
# v3 — хеш MD5 (детерминированный)
name_based_v3 = uuid.uuid3(uuid.NAMESPACE_DNS, "example.com")
# v5 — хеш SHA-1 (детерминированный, предпочтительнее v3)
name_based_v5 = uuid.uuid5(uuid.NAMESPACE_URL, "https://example.com")
print(session_id)
print(name_based_v3)
print(name_based_v5)
Где это полезно:
-
uuid4() — когда нужна просто уникальность.-
uuid1() — когда порядок по времени важен (но может раскрывать MAC-адрес и время).-
uuid3() / uuid5() — когда один и тот же «вход» должен давать один и тот же UUID (идентификатор по имени, URL и т.п.).---
### UUID как строки и обратно
Чаще всего UUID хранят как строки (например, в базе):
import uuid
order_id = uuid.uuid4()
order_str = str(order_id) # в строку
print(order_str)
restored = uuid.UUID(order_str) # обратно в объект UUID
print(restored == order_id) # True
Можно работать и с байтами:
token = uuid.uuid4()
token_bytes = token.bytes
restored_token = uuid.UUID(bytes=token_bytes)
---
### Практический мини-пример: генерация ключей для API
import uuid
def generate_api_key() -> str:
return uuid.uuid4().hex # без дефисов, 32 символа
keys = [generate_api_key() for _ in range(3)]
for k in keys:
print(k)
Метод
.hex возвращает компактное шестнадцатеричное представление, удобное для токенов.---
Модуль
uuid снимает головную боль с уникальностью: вместо придумывания схем и «умных» счётчиков достаточно вызвать одну функцию — и получить идентификатор, с которым комфортно работать и локально, и в распределённых системах.🔥2👍1
Использование
Когда файл «чуть-чуть поменяли», глазами искать отличия — то еще удовольствие. Python-модуль
---
### 1. Быстро сравнить две строки
Начнем с простого: найти различия между двумя строками посимвольно.
Результат покажет строки с префиксами:
-
-
-
Это удобно, когда нужно понять, почему строки «почти одинаковы», но сравнение
---
### 2. Похожесть строк в процентах
Иногда важно не чем строки отличаются, а насколько они похожи. Для этого есть
Значение от 0 до 1 — коэффициент похожести. Можно использовать для:
- поиска опечаток,
- подсказки «Вы имели в виду…»,
- фильтрации «почти одинаковых» записей.
---
### 3. HTML-отчет о различиях
Хотите красивый, наглядный diff в браузере?
Откройте
---
### 4. Сравнение файлов построчно
Классический сценарий — сравнить два текстовых файла:
Формат
---
difflib: как Python видит отличия лучше насКогда файл «чуть-чуть поменяли», глазами искать отличия — то еще удовольствие. Python-модуль
difflib умеет делать это аккуратно, наглядно и… очень гибко. Разберёмся, как сравнивать строки и файлы, будто у нас встроен мини-Git.---
### 1. Быстро сравнить две строки
Начнем с простого: найти различия между двумя строками посимвольно.
import difflib
s1 = "Python is awesome!"
s2 = "Python is awesom?"
diff = difflib.ndiff(s1, s2)
print("\n".join(diff))
Результат покажет строки с префиксами:
-
- — удалено-
+ — добавлено-
? — подсказка, какие именно символы отличаютсяЭто удобно, когда нужно понять, почему строки «почти одинаковы», но сравнение
== возвращает False.---
### 2. Похожесть строк в процентах
Иногда важно не чем строки отличаются, а насколько они похожи. Для этого есть
SequenceMatcher.from difflib import SequenceMatcher
a = "color"
b = "colour"
ratio = SequenceMatcher(None, a, b).ratio()
print(ratio) # например, 0.91...
Значение от 0 до 1 — коэффициент похожести. Можно использовать для:
- поиска опечаток,
- подсказки «Вы имели в виду…»,
- фильтрации «почти одинаковых» записей.
---
### 3. HTML-отчет о различиях
Хотите красивый, наглядный diff в браузере?
difflib.HtmlDiff как раз для этого:import difflib
old_lines = [
"def add(a, b):\n",
" return a + b\n",
]
new_lines = [
"def add(a, b):\n",
" result = a + b\n",
" return result\n",
]
html = difflib.HtmlDiff().make_file(old_lines, new_lines,
fromdesc="Old version",
todesc="New version")
with open("diff.html", "w", encoding="utf-8") as f:
f.write(html)
Откройте
diff.html в браузере — увидите таблицу с подсветкой добавленных/удалённых строк. Мини-система контроля версий прямо в одном файле.---
### 4. Сравнение файлов построчно
Классический сценарий — сравнить два текстовых файла:
import difflib
with open("old.txt", encoding="utf-8") as f:
old = f.readlines()
with open("new.txt", encoding="utf-8") as f:
new = f.readlines()
for line in difflib.unified_diff(old, new,
fromfile="old.txt",
tofile="new.txt"):
print(line.rstrip())
Формат
unified diff знаком всем, кто работал с Git: строки с +, - и контекстом вокруг изменений. Удобно для логов, конфигов, автопроверок.---
difflib часто недооценивают, а зря. Это готовый швейцарский нож для работы с похожими текстами: от проверки орфографии до построения собственных дифф-отчетов. И всё это — в стандартной библиотеке, без единого pip install.🔥3
Создание локального веб-сервера с помощью встроенного
Когда слышишь «веб‑сервер», в голове всплывают сложные штуки вроде Nginx, Apache или хотя бы Flask. Но в Python уже есть крошечный сервер «из коробки» — модуль
---
### Запускаем самый простой сервер
Перейдите в папку с файлами, которые хотите раздавать, и запустите:
Теперь в браузере откройте
Порт можно не указывать, тогда по умолчанию будет
---
### Минимальный сервер своим скриптом
Можно сделать то же самое из Python‑файла:
---
### Свой обработчик запросов
Хотите кастомный ответ вместо списка файлов? Наследуемся от
Теперь при открытии
---
### Когда это полезно
- Быстро показать HTML/CSS/JS без настройки больших серверов.
- Локально протестировать AJAX‑запросы.
- Написать минимальный API‑мок для отладки клиента.
http.serverКогда слышишь «веб‑сервер», в голове всплывают сложные штуки вроде Nginx, Apache или хотя бы Flask. Но в Python уже есть крошечный сервер «из коробки» — модуль
http.server. Он идеален для экспериментов, отладки и быстрых демо.---
### Запускаем самый простой сервер
Перейдите в папку с файлами, которые хотите раздавать, и запустите:
python -m http.server 8000
Теперь в браузере откройте
http://localhost:8000 — вы уже подняли сервер, который раздает текущую директорию. Порт можно не указывать, тогда по умолчанию будет
8000.---
### Минимальный сервер своим скриптом
Можно сделать то же самое из Python‑файла:
from http.server import HTTPServer, SimpleHTTPRequestHandler
def run_server(port: int = 8000):
server_address = ("", port) # "" означает слушать на всех интерфейсах
httpd = HTTPServer(server_address, SimpleHTTPRequestHandler)
print(f"Serving on port {port}...")
httpd.serve_forever()
if __name__ == "__main__":
run_server()
SimpleHTTPRequestHandler умеет раздавать файлы из текущей папки и показывает простую HTML‑страницу со списком файлов.---
### Свой обработчик запросов
Хотите кастомный ответ вместо списка файлов? Наследуемся от
BaseHTTPRequestHandler:from http.server import HTTPServer, BaseHTTPRequestHandler
class HelloHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
message = "Hello, Python beginner!"
else:
message = f"Unknown path: {self.path}"
data = message.encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
def run_server(port: int = 8080):
server_address = ("", port)
httpd = HTTPServer(server_address, HelloHandler)
print(f"Custom server on port {port}...")
httpd.serve_forever()
if __name__ == "__main__":
run_server()
Теперь при открытии
http://localhost:8080/ вы получите текстовый ответ, а при переходе по другому пути — сообщение с этим путем.---
### Когда это полезно
- Быстро показать HTML/CSS/JS без настройки больших серверов.
- Локально протестировать AJAX‑запросы.
- Написать минимальный API‑мок для отладки клиента.
http.server не для продакшена: нет защиты, логики масштабирования, нормального логирования. Но для обучения он идеально показывает, как HTTP‑запрос превращается в ответ, и помогает почувствовать «скелет» любого веб‑фреймворка.👍2
### Работа с буфером ввода-вывода с помощью
Иногда хочется поработать с текстом «как с файлом», но без создания настоящего файла на диске. Для этого в Python есть удобный инструмент —
---
### Зачем вообще нужен
Типичные сценарии:
1. Тестирование кода, который работает с файлами, без создания временных файлов.
2. Промежуточная обработка строк в виде потока: удобно, когда данные приходят частями.
3. Перенаправление вывода (например,
---
### Базовый пример: пишем и читаем
Здесь
---
### Построчное чтение
Интерфейс знакомый: можно итерироваться по строкам, использовать
---
### Перенаправление
Иногда нужно собрать то, что обычно выводится в консоль:
---
### Важные нюансы
-
- Метод
- Не забывайте про
io.StringIOИногда хочется поработать с текстом «как с файлом», но без создания настоящего файла на диске. Для этого в Python есть удобный инструмент —
io.StringIO. Это такой «файлик в памяти»: его можно читать, писать в него, перематывать курсор — почти как с обычным файлом.---
### Зачем вообще нужен
StringIO?Типичные сценарии:
1. Тестирование кода, который работает с файлами, без создания временных файлов.
2. Промежуточная обработка строк в виде потока: удобно, когда данные приходят частями.
3. Перенаправление вывода (например,
print) в строку, чтобы потом её обработать.---
### Базовый пример: пишем и читаем
from io import StringIO
buffer = StringIO()
buffer.write("Hello, world!\n")
buffer.write("This is in-memory file.\n")
# Перемещаем курсор в начало, как после открытия файла для чтения
buffer.seek(0)
content = buffer.read()
print(content)
Здесь
buffer ведет себя почти как файл, но все хранится в оперативной памяти в виде строки.---
### Построчное чтение
from io import StringIO
data = "line 1\nline 2\nline 3\n"
buffer = StringIO(data)
for line in buffer:
print(line.strip())
Интерфейс знакомый: можно итерироваться по строкам, использовать
readline(), readlines() и т.д.---
### Перенаправление
print в строкуИногда нужно собрать то, что обычно выводится в консоль:
from io import StringIO
import sys
buffer = StringIO()
stdout_backup = sys.stdout
try:
sys.stdout = buffer
print("First line")
print("Second line")
finally:
sys.stdout = stdout_backup
result = buffer.getvalue()
print("Captured:")
print(result)
buffer.getvalue() возвращает всю накопленную строку. Удобно для логирования и тестов.---
### Важные нюансы
-
StringIO работает только с текстом (str). Для байтов используйте io.BytesIO.- Метод
getvalue() можно вызывать сколько угодно раз — он не сдвигает курсор.- Не забывайте про
seek(0), если хотите перечитать содержимое с начала.io.StringIO — отличный способ тренироваться с файловым API, не засоряя диск, и гибкий инструмент для чистого и удобного кода при работе с текстовыми потоками.👍1🔥1
Генерация диаграмм с pygraphviz: основы визуализации графов
Иногда проще один раз увидеть, чем сто раз распечатать
---
### Установка
Важно: на некоторых системах сначала нужно установить сам Graphviz (через пакетный менеджер ОС).
---
### Простейший граф
Создадим ориентированный граф и сохраним его как PNG:
---
### Стайлинг: делаем диаграмму понятной
Граф без стиля — это просто клубок линий. Добавим цвета и формы, чтобы по диаграмме можно было ориентироваться за секунды:
Ключевые идеи:
-
-
-
---
### Быстрая визуализация структур из кода
---
Иногда проще один раз увидеть, чем сто раз распечатать
print(). Особенно когда дело касается связей: кто с кем соединен, в каком направлении идет поток данных, как устроена архитектура проекта. Для этого отлично подходит pygraphviz — оболочка над знаменитым Graphviz, позволяющая генерировать диаграммы прямо из Python.---
### Установка
pip install pygraphviz
Важно: на некоторых системах сначала нужно установить сам Graphviz (через пакетный менеджер ОС).
---
### Простейший граф
Создадим ориентированный граф и сохраним его как PNG:
from pygraphviz import AGraph
g = AGraph(directed=True)
g.add_node("User")
g.add_node("API")
g.add_node("DB")
g.add_edge("User", "API")
g.add_edge("API", "DB")
g.layout(prog="dot") # алгоритм раскладки
g.draw("simple_graph.png")
prog="dot" — классический и самый читаемый для иерархических структур (запросы сверху, база снизу).---
### Стайлинг: делаем диаграмму понятной
Граф без стиля — это просто клубок линий. Добавим цвета и формы, чтобы по диаграмме можно было ориентироваться за секунды:
from pygraphviz import AGraph
g = AGraph(directed=True, strict=True, rankdir="LR") # слева направо
g.add_node("Client", shape="box", style="filled", fillcolor="#AED6F1")
g.add_node("Service", shape="ellipse", style="filled", fillcolor="#A9DFBF")
g.add_node("Cache", shape="diamond", style="filled", fillcolor="#F9E79F")
g.add_edge("Client", "Service", label="HTTP")
g.add_edge("Service", "Cache", label="GET")
g.add_edge("Cache", "Service", label="HIT", color="green")
g.add_edge("Service", "Client", label="Response", color="blue")
g.graph_attr.update(label="Request Flow", fontsize="20")
g.layout(prog="dot")
g.draw("styled_graph.png")
Ключевые идеи:
-
rankdir="LR" — направление слева направо (удобно для потоков).-
shape, fillcolor, style — визуальное кодирование типов узлов.-
label и color у ребер помогают понимать протоколы, типы взаимодействия и т.п.---
### Быстрая визуализация структур из кода
pygraphviz удобно использовать для генерации диаграмм по данным из программы: граф зависимостей модулей, цепочка этапов обработки данных, схема микросервисов. Достаточно обхода вашей структуры (словаря, списка связей, дерева) и вызова add_node / add_edge в цикле.---
pygraphviz хорош тем, что избавляет от ручного рисования схем в редакторах: диаграмма становится частью кода, обновляется автоматически и всегда соответствует реальности. Для начинающего питониста это отличный инструмент, чтобы увидеть свои структуры данных и архитектуру, а не только представлять их в голове.👍1
Используем
Работа с файлами в Python часто начинается с модуля
Подключается просто:
## Копирование файлов
Базовый вариант —
Если нужны максимально точные «клоны» файла, есть
Разница — в сохранении метаданных (atime, mtime и т.п.). Для бэкапов это часто критично.
## Копирование папок
Для директорий используется
Важно: если
Так можно «обновлять» уже существующую папку бэкапа.
## Удаление файлов и папок
Одиночные файлы удобнее удалять через
Команда безвозвратная: корзины не будет, поэтому перед вызовом стоит дважды проверить путь или добавить «защиту от дурака»:
## Мини-утилита «скопировать и почистить»
Соберём всё вместе: скопируем папку и удалим старую:
Фактически мы реализовали аналог «перемещения» папки силами
---
shutil: копируем и удаляем файлы без болиРабота с файлами в Python часто начинается с модуля
os, но как только дело доходит до копирования и целых папок — на сцену выходит shutil. Это такой «швейцарский нож» для файловой системы.Подключается просто:
import shutil
from pathlib import Path
## Копирование файлов
Базовый вариант —
shutil.copy():src = Path("data/source.txt")
dst = Path("backup/source_copy.txt")
shutil.copy(src, dst)
copy переносит содержимое и права доступа, но не метаданные (например, время изменения).Если нужны максимально точные «клоны» файла, есть
copy2:shutil.copy2(src, dst)
Разница — в сохранении метаданных (atime, mtime и т.п.). Для бэкапов это часто критично.
## Копирование папок
Для директорий используется
copytree:src_dir = Path("data")
dst_dir = Path("data_backup")
shutil.copytree(src_dir, dst_dir)
Важно: если
data_backup уже существует, будет ошибка. В Python 3.8+ можно указать dirs_exist_ok=True:shutil.copytree(src_dir, dst_dir, dirs_exist_ok=True)
Так можно «обновлять» уже существующую папку бэкапа.
## Удаление файлов и папок
Одиночные файлы удобнее удалять через
Path.unlink(), а вот для целых деревьев директорий есть rmtree:target_dir = Path("old_logs")
shutil.rmtree(target_dir)
Команда безвозвратная: корзины не будет, поэтому перед вызовом стоит дважды проверить путь или добавить «защиту от дурака»:
if "backup" in str(target_dir):
shutil.rmtree(target_dir)
## Мини-утилита «скопировать и почистить»
Соберём всё вместе: скопируем папку и удалим старую:
def move_folder(src: Path, dst: Path):
shutil.copytree(src, dst, dirs_exist_ok=True)
shutil.rmtree(src)
move_folder(Path("tmp_uploads"), Path("storage/uploads"))
Фактически мы реализовали аналог «перемещения» папки силами
shutil.---
shutil хорош тем, что закрывает 80% задач по управлению файлами: копирование, рекурсивные операции, бэкапы, чистка временных директорий. А главное — код остаётся коротким и читаемым, без ручного обхода каталогов и велосипедов на os.listdir().🔥2👍1
Создание фейковых данных для тестирования с библиотекой Faker
Тестовые данные — боль любого начинающего разработчика. Ручное заполнение таблиц “Иван Иванов, test@test.ru, 123456” быстро превращает жизнь в скуку. К счастью, есть библиотека Faker, которая генерирует реалистичные фейковые данные: имена, адреса, телефоны, даты, тексты и даже фейковые компании.
---
## Установка
Базовое использование:
Каждый вызов вернет новое случайное, но правдоподобное значение.
---
## Локализация данных
Если вы тестируете российское приложение, логичнее видеть “Иван Петров”, а не “John Smith”:
Faker поддерживает десятки локалей:
---
## Генерация набора тестовых пользователей
Допустим, нужно быстро заполнить базу 10 фейковыми пользователями:
Метод
---
## Фейковые данные для API и фронтенда
Нужно протестировать список товаров или карточек в интерфейсе? Не проблема:
---
## Фиксация “сидов” для повторяемости
Важно, чтобы при тестах данные могли воспроизводиться. Для этого задаем seed:
---
Faker экономит часы рутины, делает тестовые данные живыми и разнообразными, а ваш код — более надежным. Попробуйте заменить все “test123” в ваших проектах на фейковые, но правдоподобные данные и посмотрите, сколько багов всплывет.
Тестовые данные — боль любого начинающего разработчика. Ручное заполнение таблиц “Иван Иванов, test@test.ru, 123456” быстро превращает жизнь в скуку. К счастью, есть библиотека Faker, которая генерирует реалистичные фейковые данные: имена, адреса, телефоны, даты, тексты и даже фейковые компании.
---
## Установка
pip install faker
Базовое использование:
from faker import Faker
fake = Faker()
print(fake.name())
print(fake.email())
print(fake.address())
Каждый вызов вернет новое случайное, но правдоподобное значение.
---
## Локализация данных
Если вы тестируете российское приложение, логичнее видеть “Иван Петров”, а не “John Smith”:
from faker import Faker
fake = Faker("ru_RU")
for _ in range(3):
print(fake.name(), "-", fake.phone_number())
Faker поддерживает десятки локалей:
en_US, de_DE, fr_FR и т.д.---
## Генерация набора тестовых пользователей
Допустим, нужно быстро заполнить базу 10 фейковыми пользователями:
from faker import Faker
fake = Faker("ru_RU")
def generate_user():
return {
"name": fake.name(),
"email": fake.unique.email(),
"address": fake.address(),
"birthdate": fake.date_of_birth(minimum_age=18, maximum_age=65),
}
users = [generate_user() for _ in range(10)]
for user in users:
print(user)
Метод
fake.unique гарантирует уникальность значения (пока не исчерпан генератор).---
## Фейковые данные для API и фронтенда
Нужно протестировать список товаров или карточек в интерфейсе? Не проблема:
from faker import Faker
import random
fake = Faker()
def generate_product():
return {
"id": fake.uuid4(),
"title": fake.sentence(nb_words=3),
"price": round(random.uniform(10, 500), 2),
"description": fake.text(max_nb_chars=80),
"in_stock": fake.boolean(chance_of_getting_true=80),
}
products = [generate_product() for _ in range(5)]
for product in products:
print(product)
---
## Фиксация “сидов” для повторяемости
Важно, чтобы при тестах данные могли воспроизводиться. Для этого задаем seed:
from faker import Faker
fake = Faker()
Faker.seed(42)
print(fake.name())
print(fake.name()) # при повторном запуске будут те же значения
---
Faker экономит часы рутины, делает тестовые данные живыми и разнообразными, а ваш код — более надежным. Попробуйте заменить все “test123” в ваших проектах на фейковые, но правдоподобные данные и посмотрите, сколько багов всплывет.
👍4