Создание локального веб-сервера с помощью встроенного
Когда слышишь «веб‑сервер», в голове всплывают сложные штуки вроде 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
Изучаем таймеры и замеры времени с модулем
Когда код работает медленно, интуиция часто подводит. Кажется, что «вот это место точно тормозит», а на деле время утекает в другом участке. Здесь на сцену выходит модуль
### Почему не
Наивный подход:
Проблемы:
- одно измерение: могли попасть на фоновую нагрузку системы;
- точность зависит от платформы;
- неудобно сравнивать несколько вариантов.
### Базовый пример использования
Минимальный пример из консоли:
Параметры важны:
- первый аргумент — строка с кодом, который измеряем;
-
Но писать код в строках не всегда удобно. Лучше использовать функции и параметр
Так проще рефакторить и отлаживать.
### Сравниваем два варианта кода
Предположим, мы хотим понять, что быстрее: список или генератор в
На малых диапазонах разница может быть микроскопической, но тенденцию видно: списки часто чуть медленнее, потому что требуют дополнительной памяти.
### Использование
Если нужна подготовка данных, её не стоит включать в измеряемый код. Для этого есть
Здесь:
- в
- в
### Немного удобства:
Чтобы понять разброс по времени, используйте
Так можно ориентироваться на минимум как на «лучшие условия» выполнения.
---
timeitКогда код работает медленно, интуиция часто подводит. Кажется, что «вот это место точно тормозит», а на деле время утекает в другом участке. Здесь на сцену выходит модуль
timeit — простой способ точно измерить, что действительно медленнее, а что быстрее.### Почему не
time.time()?Наивный подход:
import time
start = time.time()
result = sum(range(10_000_000))
end = time.time()
print(end - start)
Проблемы:
- одно измерение: могли попасть на фоновую нагрузку системы;
- точность зависит от платформы;
- неудобно сравнивать несколько вариантов.
timeit решает это: он запускает код много раз, считает среднее время и делает это максимально «чисто».### Базовый пример использования
Минимальный пример из консоли:
import timeit
t = timeit.timeit("sum(range(1000))", number=10000)
print(t)
Параметры важны:
- первый аргумент — строка с кодом, который измеряем;
-
number — сколько раз выполнить этот код.Но писать код в строках не всегда удобно. Лучше использовать функции и параметр
stmt как объект:import timeit
def calc():
return sum(range(1000))
t = timeit.timeit(stmt=calc, number=10000)
print(t)
Так проще рефакторить и отлаживать.
### Сравниваем два варианта кода
Предположим, мы хотим понять, что быстрее: список или генератор в
sum.import timeit
def use_list():
return sum([i for i in range(1000)])
def use_gen():
return sum(i for i in range(1000))
t_list = timeit.timeit(use_list, number=10000)
t_gen = timeit.timeit(use_gen, number=10000)
print("list:", t_list)
print("gen :", t_gen)
На малых диапазонах разница может быть микроскопической, но тенденцию видно: списки часто чуть медленнее, потому что требуют дополнительной памяти.
### Использование
setupЕсли нужна подготовка данных, её не стоит включать в измеряемый код. Для этого есть
setup:import timeit
setup_code = "data = list(range(10000))"
stmt_code = """
result = 0
for x in data:
result += x
"""
t = timeit.timeit(stmt=stmt_code, setup=setup_code, number=1000)
print(t)
Здесь:
- в
setup мы генерируем данные один раз для каждого прогона timeit;- в
stmt считаем время только самого алгоритма.### Немного удобства:
repeatЧтобы понять разброс по времени, используйте
repeat:import timeit
def func():
return sum(range(10_000))
times = timeit.repeat(func, number=1000, repeat=5)
print(times) # список из 5 измерений
print("best:", min(times))
Так можно ориентироваться на минимум как на «лучшие условия» выполнения.
---
timeit — это карманный профилировщик для микробенчмарков. Он не заменяет полноценный профилировщик, но идеально подходит, когда нужно честно ответить на вопрос: «Этот способ действительно быстрее, или мне только кажется?»🔥4
Как использовать модуль
Когда файлов становится много, а отправить нужно «всё и сразу», на сцену выходит модуль
---
### Создаем ZIP‑архив из одного файла
Минимальный пример:
Что здесь происходит:
-
-
-
---
### Добавляем несколько файлов и папку
Чтобы пройтись по директории и заархивировать всё, что внутри:
Ключевой момент —
---
### Извлекаем архив целиком или выборочно
Извлечь всё содержимое очень просто:
А вот выборочное извлечение:
---
### Проверяем содержимое без распаковки
Иногда нужно просто «подглядеть» внутрь ZIP:
Так можно быстро оценить структуру и размер архива.
---
zipfile для создания и извлечения архивовКогда файлов становится много, а отправить нужно «всё и сразу», на сцену выходит модуль
zipfile. Он входит в стандартную библиотеку Python, так что ничего устанавливать не нужно.---
### Создаем ZIP‑архив из одного файла
Минимальный пример:
import zipfile
with zipfile.ZipFile("data.zip", mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
zf.write("report.txt", arcname="report_in_zip.txt")
Что здесь происходит:
-
mode="w" — создаем новый архив (старый будет перезаписан).-
compression=ZIP_DEFLATED — обычное сжатие ZIP.-
write("report.txt", arcname=...) — первое имя — исходный файл, второе — как он будет называться внутри архива.---
### Добавляем несколько файлов и папку
Чтобы пройтись по директории и заархивировать всё, что внутри:
import zipfile
import os
def zip_folder(folder_path, zip_name):
with zipfile.ZipFile(zip_name, "w", zipfile.ZIP_DEFLATED) as zf:
for root, dirs, files in os.walk(folder_path):
for file_name in files:
full_path = os.path.join(root, file_name)
rel_path = os.path.relpath(full_path, folder_path)
zf.write(full_path, arcname=rel_path)
zip_folder("project", "project_backup.zip")
Ключевой момент —
rel_path. Благодаря относительному пути структура папок в архиве сохраняется аккуратно, без длинных системных путей.---
### Извлекаем архив целиком или выборочно
Извлечь всё содержимое очень просто:
import zipfile
with zipfile.ZipFile("project_backup.zip", "r") as zf:
zf.extractall("restored_project")
А вот выборочное извлечение:
import zipfile
with zipfile.ZipFile("project_backup.zip", "r") as zf:
for name in zf.namelist():
if name.endswith(".py"):
zf.extract(name, "only_scripts")
namelist() возвращает список файлов внутри архива. Можно фильтровать по расширению, имени и т.д.---
### Проверяем содержимое без распаковки
Иногда нужно просто «подглядеть» внутрь ZIP:
import zipfile
with zipfile.ZipFile("project_backup.zip", "r") as zf:
for info in zf.infolist():
print(info.filename, info.file_size, "bytes")
Так можно быстро оценить структуру и размер архива.
---
zipfile полезен для бэкапов, упаковки логов, раздачи учебных проектов и автоматизации рутины. Освоив эти несколько приёмов, вы легко встроите архивирование прямо в свои скрипты.👍2
Python для начинающих: приручаем командную строку с argparse
Рано или поздно любой скрипт вырастает из стадии «запустить и забыть» и ему хочется передавать параметры: путь к файлу, режим работы, уровень детализации логов. Жестко прописывать это в коде неудобно – каждый раз править и перезапускать. Тут и появляется герой дня — модуль
### Базовый пример: скрипт-калькулятор
Сделаем простой калькулятор, который принимает числа и операцию из командной строки:
Теперь можно запускать так:
Позиционные аргументы (
### Флаги и логические переключатели
Частая задача — включить «болтливый» режим:
Флаг без значения, просто включается при наличии в командной строке.
### Значения по умолчанию и типы
Попробуйте передать строку вместо числа — будет аккуратное сообщение с подсказкой по использованию.
### Подкоманды: один скрипт — много режимов
Когда скрипт начинает «разрастаться», удобно завести подкоманды, как у
Запуск:
Рано или поздно любой скрипт вырастает из стадии «запустить и забыть» и ему хочется передавать параметры: путь к файлу, режим работы, уровень детализации логов. Жестко прописывать это в коде неудобно – каждый раз править и перезапускать. Тут и появляется герой дня — модуль
argparse.### Базовый пример: скрипт-калькулятор
Сделаем простой калькулятор, который принимает числа и операцию из командной строки:
import argparse
def main():
parser = argparse.ArgumentParser(
description="Simple CLI calculator"
)
parser.add_argument("x", type=float, help="First number")
parser.add_argument("y", type=float, help="Second number")
parser.add_argument(
"--op", "-o",
choices=["add", "sub", "mul", "div"],
default="add",
help="Operation to perform"
)
args = parser.parse_args()
if args.op == "add":
result = args.x + args.y
elif args.op == "sub":
result = args.x - args.y
elif args.op == "mul":
result = args.x * args.y
elif args.op == "div":
result = args.x / args.y
print(result)
if __name__ == "__main__":
main()
Теперь можно запускать так:
python calc.py 10 5 --op mul
# 50.0
Позиционные аргументы (
x, y) обязательны, опция --op имеет значение по умолчанию и подсказку.### Флаги и логические переключатели
Частая задача — включить «болтливый» режим:
import argparse
parser = argparse.ArgumentParser(description="Demo for flags")
parser.add_argument("--verbose", "-v", action="store_true",
help="Enable verbose mode")
args = parser.parse_args()
if args.verbose:
print("Verbose mode is ON")
Флаг без значения, просто включается при наличии в командной строке.
### Значения по умолчанию и типы
argparse сам преобразует типы и выдаст внятную ошибку, если пользователь введет ерунду:parser.add_argument(
"--limit",
type=int,
default=10,
help="Max number of items (default: 10)"
)
Попробуйте передать строку вместо числа — будет аккуратное сообщение с подсказкой по использованию.
### Подкоманды: один скрипт — много режимов
Когда скрипт начинает «разрастаться», удобно завести подкоманды, как у
git (git add, git commit):import argparse
parser = argparse.ArgumentParser(description="User manager")
subparsers = parser.add_subparsers(dest="command", required=True)
add_parser = subparsers.add_parser("add", help="Add new user")
add_parser.add_argument("name")
add_parser.add_argument("--admin", action="store_true")
list_parser = subparsers.add_parser("list", help="List users")
args = parser.parse_args()
if args.command == "add":
print(f"Adding user {args.name}, admin={args.admin}")
elif args.command == "list":
print("Listing users...")
Запуск:
python usertool.py add Alice --admin
python usertool.py list
argparse берет на себя всю грязную работу по разбору аргументов, проверке типов и красивой справке. А вы концентрируетесь на логике программы, а не на парсинге строк.👍2
Как использовать
Если вам кажется, что для анализа данных нужны сложные библиотеки,
---
### Что такое
---
### Анализ текста: частота слов и букв
Классический пример — быстрый анализ текста.
Метод
---
### Подсчёт категорий: простой пример «аналитики»
Допустим, у вас есть список заказов с типами товаров:
Без циклов и лишнего кода вы уже понимаете распределение по категориям.
---
### Операции над
Так можно быстро сравнивать периоды, версии данных или сегменты пользователей.
---
### Фильтрация и преобразование результата
---
collections.Counter для простого анализа данныхЕсли вам кажется, что для анализа данных нужны сложные библиотеки,
Counter из модуля collections готов поспорить. Это маленький, но очень полезный инструмент, который превращает обычные списки и строки в наглядную статистику.---
### Что такое
CounterCounter — это специальный словарь для подсчёта количества элементов. Он считает, сколько раз встречается каждый объект, и делает это очень удобно.from collections import Counter
data = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
counter = Counter(data)
print(counter) # Counter({'apple': 3, 'banana': 2, 'orange': 1})
print(counter['apple']) # 3
Counter сразу выдаёт вам частоты элементов. Можно думать о нём как об «умном» словаре для статистики.---
### Анализ текста: частота слов и букв
Классический пример — быстрый анализ текста.
from collections import Counter
text = "data analysis with python and data tools"
words = text.split()
word_freq = Counter(words)
char_freq = Counter(text.replace(" ", ""))
print(word_freq.most_common(3)) # топ-3 самых частых слов
print(char_freq.most_common(5)) # топ-5 самых частых символов
Метод
.most_common(n) возвращает n самых популярных элементов — готовая мини-аналитика.---
### Подсчёт категорий: простой пример «аналитики»
Допустим, у вас есть список заказов с типами товаров:
from collections import Counter
orders = [
"book", "book", "laptop", "phone",
"book", "phone", "tablet", "laptop"
]
category_stats = Counter(orders)
print(category_stats) # сколько каких товаров заказали
print(category_stats.most_common(1)) # самый популярный товар
Без циклов и лишнего кода вы уже понимаете распределение по категориям.
---
### Операции над
Counter: как с многомерными счётчикамиCounter умеет складывать, вычитать и объединять данные — удобно для сравнения наборов.from collections import Counter
week1 = Counter(['book', 'book', 'phone'])
week2 = Counter(['book', 'tablet', 'phone', 'phone'])
print(week1 + week2) # суммарные продажи
print(week2 - week1) # что «добавилось» во второй неделе
Так можно быстро сравнивать периоды, версии данных или сегменты пользователей.
---
### Фильтрация и преобразование результата
Counter легко превратить в обычный словарь и отфильтровать по условию:from collections import Counter
data = ['a', 'b', 'a', 'c', 'b', 'a', 'd']
c = Counter(data)
freq = {k: v for k, v in c.items() if v > 1}
print(freq) # {'a': 3, 'b': 2}
---
collections.Counter — отличный инструмент, чтобы «понюхать данные»: быстро понять, что в них чаще всего встречается, найти лидеров и выбросы. И всё это в пару строк кода, без тяжёлых библиотек и сложной математики.👍3
Создание PDF-документов с помощью FPDF: просто, как print()
PDF — идеальный формат для чеков, отчетов, сертификатов и даже мини-отчетов по учебным проектам. В Python один из самых понятных инструментов для их создания — библиотека fpdf2 (современный форк FPDF).
---
### Установка
Базовый объект —
---
### Первый PDF за 10 строк
Создадим простой одностраничный документ с заголовком и текстом.
Ключевые моменты:
-
-
-
-
-
---
### Простой “отчет”: таблица в PDF
Сделаем мини-таблицу, например, список задач.
Здесь:
- Используем список кортежей как источник данных.
- Меняем стиль шрифта для заголовка таблицы.
-
---
### Добавление изображения
Например, логотип в шапке:
---
FPDF удобна тем, что работает “как конструктор”: просто добавляете текст, таблицы, картинки, постепенно превращая Python-скрипт в генератор аккуратных PDF-документов. Отличный навык для автоматизации отчетов и учебных проектов.
PDF — идеальный формат для чеков, отчетов, сертификатов и даже мини-отчетов по учебным проектам. В Python один из самых понятных инструментов для их создания — библиотека fpdf2 (современный форк FPDF).
---
### Установка
pip install fpdf2
Базовый объект —
FPDF, с ним и будем работать.---
### Первый PDF за 10 строк
Создадим простой одностраничный документ с заголовком и текстом.
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=16)
pdf.cell(0, 10, "Hello, PDF world!", ln=1, align="C")
pdf.set_font("Arial", size=12)
text = "This is a simple PDF generated with fpdf2 in Python."
pdf.multi_cell(0, 8, text)
pdf.output("example_basic.pdf")
Ключевые моменты:
-
add_page() — добавляем страницу.-
set_font() — выбираем шрифт и размер.-
cell() — строка текста; ln=1 переносит курсор на новую строку.-
multi_cell() — блок текста с переносами.-
output() — сохраняем файл.---
### Простой “отчет”: таблица в PDF
Сделаем мини-таблицу, например, список задач.
from fpdf import FPDF
data = [
("ID", "Task", "Status"),
("1", "Learn FPDF basics", "Done"),
("2", "Generate simple report", "In progress"),
("3", "Share PDF with team", "Pending"),
]
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", "B", 14)
pdf.cell(0, 10, "Tasks Report", ln=1, align="C")
pdf.ln(4)
pdf.set_font("Arial", size=11)
col_widths = [15, 90, 30]
for row_index, row in enumerate(data):
for col_index, text in enumerate(row):
style = "B" if row_index == 0 else ""
pdf.set_font("Arial", style, 11)
pdf.cell(col_widths[col_index], 8, text, border=1)
pdf.ln(8)
pdf.output("tasks_report.pdf")
Здесь:
- Используем список кортежей как источник данных.
- Меняем стиль шрифта для заголовка таблицы.
-
border=1 рисует рамки ячеек — уже похоже на отчет.---
### Добавление изображения
Например, логотип в шапке:
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.image("logo.png", x=10, y=8, w=30)
pdf.set_font("Arial", "B", 16)
pdf.cell(0, 10, "Company Report", ln=1, align="C")
pdf.output("report_with_logo.pdf")
---
FPDF удобна тем, что работает “как конструктор”: просто добавляете текст, таблицы, картинки, постепенно превращая Python-скрипт в генератор аккуратных PDF-документов. Отличный навык для автоматизации отчетов и учебных проектов.
👍3❤1