Создание и экспорт PDF-файлов с помощью ReportLab
PDF любят бухгалтеры, юристы и вообще все, кому важен аккуратный документ “как из принтера”. А Python это тоже умеет — с помощью библиотеки ReportLab.
---
### Установка
После этого можно собирать PDF буквально по строчкам.
---
### Самый простой PDF
Создадим файл
Пара моментов:
- Координаты считаются в поинтах (1/72 дюйма), (0, 0) — левый нижний угол.
-
---
### Добавляем шрифт и несколько строк
Можно управлять шрифтами и цветами:
Так уже можно генерировать простые счета, акты, сертификаты.
---
### Несколько страниц
PDF — не только один лист:
Каждый вызов
---
### Таблица с использованием platypus
Для отчетов удобен модуль platypus (он входит в ReportLab):
Так уже получается вполне рабочий отчет: заголовки, сетка, выравнивание.
---
ReportLab — мощный “принтер” для Python: формировать счета, договоры, пропуска, сертификаты можно автоматически, просто подставляя данные. Скрипт запускается — и через секунду готов аккуратный PDF, который не стыдно отправить клиенту.
PDF любят бухгалтеры, юристы и вообще все, кому важен аккуратный документ “как из принтера”. А Python это тоже умеет — с помощью библиотеки ReportLab.
---
### Установка
pip install reportlab
После этого можно собирать PDF буквально по строчкам.
---
### Самый простой PDF
Создадим файл
hello.pdf с одной строкой текста:from reportlab.pdfgen import canvas
def create_simple_pdf(filename):
c = canvas.Canvas(filename)
c.drawString(100, 750, "Hello, ReportLab!")
c.save()
create_simple_pdf("hello.pdf")
Пара моментов:
- Координаты считаются в поинтах (1/72 дюйма), (0, 0) — левый нижний угол.
-
save() обязателен, иначе файл будет пустым.---
### Добавляем шрифт и несколько строк
Можно управлять шрифтами и цветами:
from reportlab.pdfgen import canvas
from reportlab.lib.colors import blue, red
def create_styled_pdf(filename):
c = canvas.Canvas(filename)
c.setFont("Helvetica-Bold", 20)
c.setFillColor(blue)
c.drawString(100, 780, "Invoice #42")
c.setFont("Helvetica", 12)
c.setFillColor(red)
c.drawString(100, 750, "Customer: John Smith")
c.drawString(100, 730, "Total: $199.99")
c.save()
create_styled_pdf("invoice.pdf")
Так уже можно генерировать простые счета, акты, сертификаты.
---
### Несколько страниц
PDF — не только один лист:
from reportlab.pdfgen import canvas
def create_multipage_pdf(filename):
c = canvas.Canvas(filename)
for page_num in range(1, 4):
c.drawString(100, 750, f"Page {page_num}")
c.showPage() # переход на новую страницу
c.save()
create_multipage_pdf("multipage.pdf")
Каждый вызов
showPage() завершает текущую страницу и начинает следующую.---
### Таблица с использованием platypus
Для отчетов удобен модуль platypus (он входит в ReportLab):
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
def create_table_pdf(filename):
doc = SimpleDocTemplate(filename)
data = [
["Name", "Quantity", "Price"],
["Apples", 3, "$5"],
["Oranges", 5, "$7"],
["Bananas", 2, "$4"],
]
table = Table(data)
table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
("GRID", (0, 0), (-1, -1), 0.5, colors.black),
("ALIGN", (1, 1), (-1, -1), "CENTER"),
]))
doc.build([table])
create_table_pdf("table_report.pdf")
Так уже получается вполне рабочий отчет: заголовки, сетка, выравнивание.
---
ReportLab — мощный “принтер” для Python: формировать счета, договоры, пропуска, сертификаты можно автоматически, просто подставляя данные. Скрипт запускается — и через секунду готов аккуратный PDF, который не стыдно отправить клиенту.
👍1
Python для начинающих: основы сериализации с
Представьте, что вы написали класс, настроили кучу объектов, а программу нужно закрыть. Как сохранить их состояние, чтобы потом просто "разморозить" и продолжить? Здесь вступает в игру сериализация — превращение объекта в последовательность байт или строку, которую можно записать в файл или отправить по сети.
В Python для этого чаще всего используют два модуля:
---
##
Плюсы:
- поддерживает "почти всё" из мира Python;
- минимум кода.
Минусы:
- формат бинарный и нечитаемый человеком;
- небезопасен: никогда не загружайте pickle-файлы из непроверенных источников — там может быть произвольный вредоносный код.
---
##
Если нужно сериализовать объект своего класса, его придётся "разобрать" в словарь:
---
## Что когда использовать?
- Нужна максимальная совместимость, читаемый текст и обмен с другими языками — берите
- Нужна быстрая работа с "нативными" Python-объектами и файл не покидает ваш сервис — подойдёт
Сериализация — это способ дать вашим объектам "вторую жизнь" после завершения программы. Освоив
pickle и jsonПредставьте, что вы написали класс, настроили кучу объектов, а программу нужно закрыть. Как сохранить их состояние, чтобы потом просто "разморозить" и продолжить? Здесь вступает в игру сериализация — превращение объекта в последовательность байт или строку, которую можно записать в файл или отправить по сети.
В Python для этого чаще всего используют два модуля:
pickle и json. Они решают похожую задачу, но по-разному.---
##
pickle: все из Python — для Pythonpickle умеет сериализовать почти любые Python-объекты: списки, словари, функции, пользовательские классы.import pickle
class User:
def __init__(self, name, score):
self.name = name
self.score = score
user = User("Alice", 42)
# Сериализация в байты
data = pickle.dumps(user)
# Запись в файл
with open("user.pkl", "wb") as f:
pickle.dump(user, f)
# Чтение из файла
with open("user.pkl", "rb") as f:
loaded_user = pickle.load(f)
print(loaded_user.name, loaded_user.score) # Alice 42
Плюсы:
- поддерживает "почти всё" из мира Python;
- минимум кода.
Минусы:
- формат бинарный и нечитаемый человеком;
- небезопасен: никогда не загружайте pickle-файлы из непроверенных источников — там может быть произвольный вредоносный код.
---
##
json: читаемо, переносимо, безопаснееjson сериализует данные в текстовый формат, понятный другим языкам (JavaScript, Go, Java и т.д.). Но он понимает только простые типы: dict, list, str, int, float, bool, None.import json
user = {
"name": "Alice",
"score": 42,
"tags": ["python", "beginner"]
}
# В строку
json_str = json.dumps(user)
# В файл
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user, f, indent=4)
# Из файла
with open("user.json", "r", encoding="utf-8") as f:
loaded_user = json.load(f)
print(loaded_user["name"], loaded_user["tags"])
Если нужно сериализовать объект своего класса, его придётся "разобрать" в словарь:
class User:
def __init__(self, name, score):
self.name = name
self.score = score
def user_to_dict(user):
return {"name": user.name, "score": user.score}
user = User("Bob", 100)
json_str = json.dumps(user_to_dict(user))
---
## Что когда использовать?
- Нужна максимальная совместимость, читаемый текст и обмен с другими языками — берите
json.- Нужна быстрая работа с "нативными" Python-объектами и файл не покидает ваш сервис — подойдёт
pickle, но помните о безопасности.Сериализация — это способ дать вашим объектам "вторую жизнь" после завершения программы. Освоив
pickle и json, вы уже делаете шаг в сторону реальных приложений: конфиги, кэш, сохранения состояния и обмен данными.👍2❤1
Как использовать модуль
Когда код начинает тормозить, первым делом нужно ответить на простой вопрос: что именно работает медленно? Для этого не нужен сложный профайлер — в большинстве случаев хватит стандартного модуля
---
### 1. Быстрое измерение через
Функция
Плюс: просто и понятно.
Минус: точность зависит от системы, и эта функция не гарантирует высокую разрешающую способность.
---
### 2. Более точный замер через
Используйте
---
### 3. Сравниваем два варианта решения
Предположим, мы хотим понять, что быстрее: цикл или встроенная функция
Здесь мы запускаем каждую функцию несколько раз и берём лучший результат — так меньше влияние случайных задержек (нагрузка системы, кэш, фоновые процессы).
---
### Вывод
Модуль
- измерять скорость отдельных участков кода;
- сравнивать разные реализации;
- находить узкие места без сложных инструментов.
Запомните правило:
time для измерения скорости выполнения кодаКогда код начинает тормозить, первым делом нужно ответить на простой вопрос: что именно работает медленно? Для этого не нужен сложный профайлер — в большинстве случаев хватит стандартного модуля
time.---
### 1. Быстрое измерение через
time.time()Функция
time.time() возвращает текущее время в секундах с начала эпохи (обычно 1 января 1970). Если замерить время до и после участка кода — получим длительность его выполнения.import time
def slow_operation():
total = 0
for i in range(10_000_000):
total += i
return total
start = time.time()
result = slow_operation()
end = time.time()
elapsed = end - start
print(f"Result: {result}")
print(f"Elapsed: {elapsed:.4f} seconds")
Плюс: просто и понятно.
Минус: точность зависит от системы, и эта функция не гарантирует высокую разрешающую способность.
---
### 2. Более точный замер через
time.perf_counter()time.perf_counter() специально создан для измерения интервалов времени. Он не привязан к "реальному" времени, зато максимально точен и не страдает от смены системных часов.import time
def fast_operation():
return sum(range(10_000_000))
start = time.perf_counter()
result = fast_operation()
end = time.perf_counter()
elapsed = end - start
print(f"Result: {result}")
print(f"Elapsed: {elapsed:.6f} seconds")
Используйте
perf_counter() во всех случаях, когда вас интересует скорость кода, а не текущее время.---
### 3. Сравниваем два варианта решения
Предположим, мы хотим понять, что быстрее: цикл или встроенная функция
sum.import time
def sum_loop(n):
total = 0
for i in range(n):
total += i
return total
def sum_builtin(n):
return sum(range(n))
def measure(func, n, repeats=5):
best = float("inf")
for _ in range(repeats):
start = time.perf_counter()
func(n)
end = time.perf_counter()
elapsed = end - start
if elapsed < best:
best = elapsed
return best
n = 5_000_000
t_loop = measure(sum_loop, n)
t_builtin = measure(sum_builtin, n)
print(f"Loop: {t_loop:.6f} s")
print(f"Builtin: {t_builtin:.6f} s")
Здесь мы запускаем каждую функцию несколько раз и берём лучший результат — так меньше влияние случайных задержек (нагрузка системы, кэш, фоновые процессы).
---
### Вывод
Модуль
time — это простой, но мощный инструмент, чтобы:- измерять скорость отдельных участков кода;
- сравнивать разные реализации;
- находить узкие места без сложных инструментов.
Запомните правило:
time.time() — для "какой сейчас час", time.perf_counter() — для "как быстро это работает".🔥2
### Редактирование изображений с помощью Pillow: первые шаги в «фотошопе на Python»
Pillow — это библиотека, которая превращает Python в мини-фотошоп: можно обрезать, сжимать, накладывать текст, применять фильтры и даже собирать простые превьюшки для соцсетей.
Устанавливается просто:
Базовый импорт:
---
### Открытие и сохранение изображений
---
### Обрезка и поворот
---
### Фильтры и улучшение качества
Так можно быстро «подтянуть» резкость и контраст фото.
---
### Нанесение текста (водяной знак)
Здесь создается прозрачный слой, на который рисуется полупрозрачный текст, а затем он накладывается на оригинал.
---
### Массовая обработка изображений
Этот скрипт автоматически уменьшит и сожмет все фото в папке — полезно перед загрузкой на сайт.
---
Pillow хорош тем, что порог входа низкий: уже через пару десятков строк кода можно автоматизировать то, что обычно делается руками в графическом редакторе. А дальше — фильтры, коллажи, генерация превью, мемы и целые пайплайны обработки изображений.
Pillow — это библиотека, которая превращает Python в мини-фотошоп: можно обрезать, сжимать, накладывать текст, применять фильтры и даже собирать простые превьюшки для соцсетей.
Устанавливается просто:
pip install pillow
Базовый импорт:
from PIL import Image, ImageFilter, ImageEnhance, ImageFont, ImageDraw
---
### Открытие и сохранение изображений
from PIL import Image
img = Image.open("input.jpg") # открываем
print(img.size, img.mode, img.format)
resized = img.resize((800, 600)) # изменение размеров
resized.save("output_resized.jpg", quality=85)
quality=85 полезно для оптимизации картинок под веб.---
### Обрезка и поворот
img = Image.open("input.jpg")
# crop(left, upper, right, lower)
cropped = img.crop((100, 100, 600, 600))
rotated = cropped.rotate(30, expand=True)
rotated.save("output_cropped_rotated.png")
expand=True не обрежет картинку после поворота.---
### Фильтры и улучшение качества
from PIL import Image, ImageFilter, ImageEnhance
img = Image.open("input.jpg")
blurred = img.filter(ImageFilter.GaussianBlur(radius=2))
sharpener = ImageEnhance.Sharpness(blurred)
sharpened = sharpener.enhance(1.8) # 1.0 — без изменений
contrast = ImageEnhance.Contrast(sharpened).enhance(1.3)
contrast.save("output_filtered.jpg")
Так можно быстро «подтянуть» резкость и контраст фото.
---
### Нанесение текста (водяной знак)
from PIL import Image, ImageDraw, ImageFont
img = Image.open("input.jpg").convert("RGBA")
txt_layer = Image.new("RGBA", img.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(txt_layer)
font = ImageFont.truetype("arial.ttf", 40)
text = "myblog.dev"
text_pos = (img.size[0] - 250, img.size[1] - 60)
draw.text(text_pos, text, font=font, fill=(255, 255, 255, 120))
watermarked = Image.alpha_composite(img, txt_layer)
watermarked.convert("RGB").save("output_watermarked.jpg")
Здесь создается прозрачный слой, на который рисуется полупрозрачный текст, а затем он накладывается на оригинал.
---
### Массовая обработка изображений
import pathlib
from PIL import Image
input_dir = pathlib.Path("photos")
output_dir = pathlib.Path("photos_optimized")
output_dir.mkdir(exist_ok=True)
for path in input_dir.glob("*.jpg"):
img = Image.open(path)
img.thumbnail((1200, 1200))
img.save(output_dir / path.name, quality=80, optimize=True)
Этот скрипт автоматически уменьшит и сожмет все фото в папке — полезно перед загрузкой на сайт.
---
Pillow хорош тем, что порог входа низкий: уже через пару десятков строк кода можно автоматизировать то, что обычно делается руками в графическом редакторе. А дальше — фильтры, коллажи, генерация превью, мемы и целые пайплайны обработки изображений.
👍2
Мониторинг системных ресурсов с помощью psutil: делаем свой мини‑«Диспетчер задач»
Если вы когда‑нибудь задумывались, как Python‑скрипт может узнать, сколько у вас свободной памяти, насколько загружен процессор и кто вообще ест весь диск — вам нужен модуль
---
### Установка
---
### Базовый мониторинг CPU и памяти
Здесь:
-
-
---
### Мониторинг диска и сети
Так можно быстро понять, нагружает ли диск какой‑то процесс и есть ли сетевой трафик.
---
### Кто все это ест: процессы
Функция показывает топ процессов по использованию памяти — уже что‑то вроде урезанного списка в «Диспетчере задач».
---
Если вы когда‑нибудь задумывались, как Python‑скрипт может узнать, сколько у вас свободной памяти, насколько загружен процессор и кто вообще ест весь диск — вам нужен модуль
psutil.psutil (process and system utilities) — кроссплатформенная библиотека для работы с системной статистикой: CPU, память, диски, сеть, процессы. Идеален для небольших утилит мониторинга и первых шагов в сторону системного администрирования на Python.---
### Установка
pip install psutil
---
### Базовый мониторинг CPU и памяти
import psutil
import time
def print_basic_stats():
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory()
print(f"CPU: {cpu}%")
print(f"Memory: {mem.percent}% used ({mem.used // (1024**2)} MB / {mem.total // (1024**2)} MB)")
if __name__ == "__main__":
while True:
print_basic_stats()
time.sleep(2)
Здесь:
-
cpu_percent(interval=1) замеряет загрузку за последнюю секунду;-
virtual_memory() возвращает объект с подробной статистикой по ОЗУ.---
### Мониторинг диска и сети
import psutil
import time
def print_disk_and_net():
disk = psutil.disk_usage("/")
net1 = psutil.net_io_counters()
time.sleep(1)
net2 = psutil.net_io_counters()
sent_speed = (net2.bytes_sent - net1.bytes_sent) / 1024
recv_speed = (net2.bytes_recv - net1.bytes_recv) / 1024
print(f"Disk used: {disk.percent}%")
print(f"Net: ↑ {sent_speed:.1f} KB/s, ↓ {recv_speed:.1f} KB/s")
if __name__ == "__main__":
while True:
print_disk_and_net()
Так можно быстро понять, нагружает ли диск какой‑то процесс и есть ли сетевой трафик.
---
### Кто все это ест: процессы
import psutil
def top_memory_processes(limit=5):
processes = []
for proc in psutil.process_iter(["pid", "name", "memory_percent"]):
processes.append(proc.info)
processes.sort(key=lambda p: p["memory_percent"], reverse=True)
for p in processes[:limit]:
print(f"{p['pid']:>6} {p['memory_percent']:5.1f}% {p['name']}")
if __name__ == "__main__":
top_memory_processes()
Функция показывает топ процессов по использованию памяти — уже что‑то вроде урезанного списка в «Диспетчере задач».
---
psutil позволяет вам из простого скрипта превратиться в маленький системный «радист»: собирать метрики, логировать их, строить графики, реагировать на перегрузки. Для начинающего питониста это отличный модуль, чтобы почувствовать, что ваш код взаимодействует не только с текстовыми задачками, но и с «живой» системой.🔥2
### Простое создание ZIP-архивов с
Архивация — одна из тех задач, которые рано или поздно понадобятся почти в любом проекте: сделать бэкап, запаковать логи, отправить результаты работы скрипта. В Python это можно сделать «вручную» с модулем
---
## Вариант 1: полный контроль с
### Создание архива и добавление файлов
Что тут важно:
-
-
-
### Просмотр содержимого архива
Можно и читать файлы напрямую, не распаковывая всё:
---
## Вариант 2: быстро и просто с
Если нужен просто «запаковать папку целиком» —
Можно так же легко создавать не только ZIP, но и
---
## Когда что использовать?
-
-
Оба модуля входят в стандартную библиотеку, так что никаких дополнительных установок — просто импортируйте и архивируйте.
zipfile и shutilАрхивация — одна из тех задач, которые рано или поздно понадобятся почти в любом проекте: сделать бэкап, запаковать логи, отправить результаты работы скрипта. В Python это можно сделать «вручную» с модулем
zipfile, а можно — «по-быстрому» с shutil. Разберём оба подхода.---
## Вариант 1: полный контроль с
zipfilezipfile даёт гибкость: можно выбирать режимы сжатия, добавлять отдельные файлы и целые папки, читать содержимое архива.### Создание архива и добавление файлов
import zipfile
from pathlib import Path
base_dir = Path("project_data")
zip_path = Path("backup.zip")
with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
for file_path in base_dir.rglob("*"):
if file_path.is_file():
arc_name = file_path.relative_to(base_dir)
zf.write(file_path, arcname=arc_name)
print(f"Created archive: {zip_path}")
Что тут важно:
-
mode="w" — создать новый архив (перезапишет существующий).-
ZIP_DEFLATED — стандартное сжатие.-
relative_to(base_dir) — в архив не попадут «лишние» абсолютные пути.### Просмотр содержимого архива
import zipfile
with zipfile.ZipFile("backup.zip", "r") as zf:
print(zf.namelist())
Можно и читать файлы напрямую, не распаковывая всё:
with zipfile.ZipFile("backup.zip", "r") as zf:
with zf.open("subdir/report.txt") as f:
content = f.read().decode("utf-8")
print(content)
---
## Вариант 2: быстро и просто с
shutilЕсли нужен просто «запаковать папку целиком» —
shutil.make_archive делает это одной строкой.import shutil
from pathlib import Path
base_dir = Path("project_data")
archive_path = shutil.make_archive(
base_name="project_backup", # будет project_backup.zip
format="zip",
root_dir=base_dir
)
print(f"Archive created at: {archive_path}")
Можно так же легко создавать не только ZIP, но и
tar, gztar, bztar.---
## Когда что использовать?
-
zipfile — когда нужен контроль: выбор файлов, чтение из архива, выбор метода сжатия, обновление существующего архива.-
shutil — когда задача проста: «возьми эту папку и сделай из неё ZIP».Оба модуля входят в стандартную библиотеку, так что никаких дополнительных установок — просто импортируйте и архивируйте.
👍1
Как класть и извлекать данные из стека и очереди:
Если вам нужны стек или очередь в Python, не спешите писать свои классы. В стандартной библиотеке уже есть мощный инструмент —
---
## Быстрый старт
---
##
Стек — это принцип “последним пришёл — первым вышел” (LIFO). Для стека нам нужны две операции: положить и достать с одного и того же конца.
Здесь
---
##
Очередь — “первым пришёл — первым вышел” (FIFO). Добавляем в конец, забираем из начала.
Ключевой метод —
---
## Двусторонняя очередь
Иногда удобно, что
Так можно, например, реализовать “слайдящуюся” историю последних N элементов.
---
## Ограниченный размер:
Полезно для логов, последних измерений, кэшей.
---
Главное: запомните четыре метода —
deque из collectionsЕсли вам нужны стек или очередь в Python, не спешите писать свои классы. В стандартной библиотеке уже есть мощный инструмент —
collections.deque. Это двусторонняя очередь, но из неё легко сделать и стек, и обычную очередь.---
## Быстрый старт
from collections import deque
dq = deque() # пустая deque
dq = deque([1, 2, 3]) # инициализация с данными
deque оптимизирован под операции добавления/удаления с обоих концов — в отличие от обычного списка, где pop(0) и insert(0, x) работают медленно.---
##
deque как стек (LIFO)Стек — это принцип “последним пришёл — первым вышел” (LIFO). Для стека нам нужны две операции: положить и достать с одного и того же конца.
from collections import deque
stack = deque()
# кладём в стек
stack.append("page_1")
stack.append("page_2")
stack.append("page_3")
# достаём из стека
last_page = stack.pop() # "page_3"
prev_page = stack.pop() # "page_2"
Здесь
append() и pop() работают с “хвостом” очереди. Именно так строится история переходов в браузере, отмена действий в редакторе и т.п.---
##
deque как очередь (FIFO)Очередь — “первым пришёл — первым вышел” (FIFO). Добавляем в конец, забираем из начала.
from collections import deque
queue = deque()
# приходят задачи
queue.append("task_1")
queue.append("task_2")
queue.append("task_3")
# обрабатываем в порядке поступления
first = queue.popleft() # "task_1"
second = queue.popleft() # "task_2"
Ключевой метод —
popleft(): быстро забирает элемент с начала. Для списка аналог pop(0) был бы заметно медленнее.---
## Двусторонняя очередь
Иногда удобно, что
deque — двусторонняя:from collections import deque
dq = deque([2, 3])
dq.appendleft(1) # слева: [1, 2, 3]
dq.append(4) # справа: [1, 2, 3, 4]
left = dq.popleft() # 1
right = dq.pop() # 4
Так можно, например, реализовать “слайдящуюся” историю последних N элементов.
---
## Ограниченный размер:
maxlendeque умеет автоматически забывать старые элементы:from collections import deque
history = deque(maxlen=3)
for i in range(5):
history.append(i)
print(history) # deque([2, 3, 4], maxlen=3)
Полезно для логов, последних измерений, кэшей.
---
Главное: запомните четыре метода —
append, appendleft, pop, popleft. С их помощью вы можете построить стек, очередь и даже более сложные структуры, не выходя за рамки стандартной библиотеки Python.👍2
Python для начинающих: создаём удобные CLI-интерфейсы с argparse
Большинство утилит в терминале — это просто программы с аргументами командной строки.
### Минимальный пример
Начнём с простого: создадим скрипт, который приветствует пользователя.
Теперь в терминале:
- парсит аргументы,
- проверяет типы (
- подставляет значения по умолчанию (
- показывает аккуратную справку:
### Флаги и режимы работы
Добавим флаг, который ничего не принимает, но меняет поведение:
Ключевой момент —
### Подкоманды: как
Аргументы можно группировать в подкоманды:
Теперь:
Так строятся целые консольные инструменты: один файл — множество команд.
### Почему стоит привыкнуть к argparse
- Встроен в стандартную библиотеку, без лишних зависимостей.
- Автоматически генерирует
- Делает интерфейс предсказуемым и профессиональным.
- Легко расширяется: типы, значения по умолчанию, подкоманды, обязательные/необязательные аргументы.
Один раз освоив
Большинство утилит в терминале — это просто программы с аргументами командной строки.
python script.py --input data.txt --verbose выглядит профессионально и удобно. За этим стоит стандартная библиотека argparse, которую многие новички игнорируют, а зря.### Минимальный пример
Начнём с простого: создадим скрипт, который приветствует пользователя.
import argparse
def main():
parser = argparse.ArgumentParser(
description="Simple greeting script"
)
parser.add_argument(
"name",
help="User name to greet"
)
parser.add_argument(
"-t", "--times",
type=int,
default=1,
help="How many times to print greeting"
)
args = parser.parse_args()
for _ in range(args.times):
print(f"Hello, {args.name}!")
if __name__ == "__main__":
main()
Теперь в терминале:
python greet.py Alice
python greet.py Alice --times 3
argparse сам:- парсит аргументы,
- проверяет типы (
type=int),- подставляет значения по умолчанию (
default=1),- показывает аккуратную справку:
python greet.py -h.### Флаги и режимы работы
Добавим флаг, который ничего не принимает, но меняет поведение:
import argparse
def main():
parser = argparse.ArgumentParser(
description="File size checker"
)
parser.add_argument("path", help="Path to file")
parser.add_argument(
"-q", "--quiet",
action="store_true",
help="Print only raw size in bytes"
)
args = parser.parse_args()
import os
size = os.path.getsize(args.path)
if args.quiet:
print(size)
else:
print(f"File: {args.path}")
print(f"Size: {size} bytes")
if __name__ == "__main__":
main()
Ключевой момент —
action="store_true": если флаг указан, в args.quiet будет True, иначе False.### Подкоманды: как
git clone, git statusАргументы можно группировать в подкоманды:
import argparse
def cmd_add(args):
print(args.x + args.y)
def cmd_mul(args):
print(args.x * args.y)
def main():
parser = argparse.ArgumentParser(
description="Simple calculator"
)
subparsers = parser.add_subparsers(
dest="command",
required=True
)
parser_add = subparsers.add_parser("add", help="Add numbers")
parser_add.add_argument("x", type=int)
parser_add.add_argument("y", type=int)
parser_add.set_defaults(func=cmd_add)
parser_mul = subparsers.add_parser("mul", help="Multiply numbers")
parser_mul.add_argument("x", type=int)
parser_mul.add_argument("y", type=int)
parser_mul.set_defaults(func=cmd_mul)
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
main()
Теперь:
python calc.py add 2 3 # 5
python calc.py mul 2 3 # 6
Так строятся целые консольные инструменты: один файл — множество команд.
### Почему стоит привыкнуть к argparse
- Встроен в стандартную библиотеку, без лишних зависимостей.
- Автоматически генерирует
--help.- Делает интерфейс предсказуемым и профессиональным.
- Легко расширяется: типы, значения по умолчанию, подкоманды, обязательные/необязательные аргументы.
Один раз освоив
argparse, вы перестаёте писать input() в каждом втором скрипте и начинаете создавать настоящие консольные утилиты. Это маленький шаг в коде, но большой шаг к тому, чтобы ваши программы выглядели как «настоящие инструменты», а не учебные примеры.🔥3❤1
Преобразование строк и чисел с помощью форматирования f-строк
Если вы все еще конкатенируете строки через
---
### Базовый синтаксис
F-строка — это строка с буквой
Уже лучше, чем
---
### Форматирование чисел
Главная магия начинается, когда нужно красиво отобразить числа.
Количество знаков после запятой:
Разделение разрядов:
Запятая или нижнее подчеркивание помогают “читать” большие числа.
Проценты:
---
### Выравнивание и ширина
Можно управлять тем, как текст и числа “лежат” в строке — удобно для табличного вывода.
-
-
Вывод будет аккуратно выровнен по столбцам.
---
### Форматирование чисел в разных системах счисления
---
### Вложенные выражения и функции
В f-строках можно вызывать функции и писать выражения:
---
### Быстрая диагностика: =
С Python 3.8 появилось удобство для отладки:
---
F-строки — это компактный, выразительный и очень мощный способ преобразовывать и форматировать строки и числа. Освоив их, вы заметите, насколько чище и понятнее станет ваш код.
Если вы все еще конкатенируете строки через
+, самое время остановиться. В Python есть более мощный и удобный инструмент — f-строки (formatted string literals). Они не только делают код читаемее, но и позволяют красиво преобразовывать числа и строки буквально “на лету”.---
### Базовый синтаксис
F-строка — это строка с буквой
f перед кавычками. Внутри фигурных скобок {} можно писать выражения:name = "Alice"
age = 25
text = f"Name: {name}, age: {age}"
print(text) # Name: Alice, age: 25
Уже лучше, чем
"Name: " + name + ", age: " + str(age).---
### Форматирование чисел
Главная магия начинается, когда нужно красиво отобразить числа.
Количество знаков после запятой:
price = 12.34567
print(f"{price:.2f}") # 12.35
print(f"{price:.0f}") # 12
.2f — два знака после запятой, .0f — без дробной части.Разделение разрядов:
big_num = 1234567890
print(f"{big_num:,}") # 1,234,567,890
print(f"{big_num:_}") # 1_234_567_890
Запятая или нижнее подчеркивание помогают “читать” большие числа.
Проценты:
ratio = 0.0789
print(f"{ratio:.2%}") # 7.89%
---
### Выравнивание и ширина
Можно управлять тем, как текст и числа “лежат” в строке — удобно для табличного вывода.
items = [("Apple", 3.5), ("Banana", 12.0), ("Kiwi", 0.95)]
for name, price in items:
print(f"{name:<10} | {price:>7.2f}")
-
<10 — выравнивание по левому краю, ширина 10 символов -
>7.2f — по правому краю, ширина 7, два знака после запятойВывод будет аккуратно выровнен по столбцам.
---
### Форматирование чисел в разных системах счисления
num = 42
print(f"bin: {num:b}") # bin: 101010
print(f"hex: {num:x}") # hex: 2a
print(f"HEX: {num:#X}") # HEX: 0X2A
# добавляет префикс 0b, 0x, 0o.---
### Вложенные выражения и функции
В f-строках можно вызывать функции и писать выражения:
import math
x = 2
print(f"sqrt({x}) = {math.sqrt(x):.3f}")
print(f"{x}! = {math.factorial(x)}")
---
### Быстрая диагностика: =
С Python 3.8 появилось удобство для отладки:
=a = 7
b = 3
print(f"{a=}, {b=}, sum={a + b}")
# a=7, b=3, sum=10
---
F-строки — это компактный, выразительный и очень мощный способ преобразовывать и форматировать строки и числа. Освоив их, вы заметите, насколько чище и понятнее станет ваш код.
👍6
Создание таплов и однострочных функций с помощью
Python любит, когда код короткий и понятный. Сегодня разберём связку, которая идеально подходит для “быстрых” преобразований данных:
---
### 1. Что такое
Обычная функция:
То же самое с
А можно вообще не присваивать её переменной, а использовать сразу в выражении — и вот тут в игру вступает
---
### 2.
Типичный пример:
Обрати внимание:
---
### 3. Создаём таплы с помощью
Допустим, у нас есть список чисел, и мы хотим получить кортеж пар
Здесь важно:
-
-
-
---
### 4. Комбинируем несколько итерируемых объектов
Так можно элегантно “склеивать” данные без явных циклов.
---
### 5. Однострочные конвейеры преобразований
Связка
Считываем строки → сразу превращаем в числа → сразу умножаем.
---
### Когда это оправдано
- Нужно быстро преобразовать последовательность.
- Логика простая и умещается в одну строку.
- Нужен результат именно в виде кортежей (например, для неизменяемых данных или в качестве ключей словаря).
Если выражение становится громоздким и трудно читаемым — лучше вернуться к обычным функциям и циклам. Но для небольших преобразований
lambda и mapPython любит, когда код короткий и понятный. Сегодня разберём связку, которая идеально подходит для “быстрых” преобразований данных:
lambda + map + кортежи (tuples).---
### 1. Что такое
lambda и зачем она нужнаlambda — это способ создать функцию “на лету”, прямо внутри выражения, без def и имени.Обычная функция:
def square(x):
return x ** 2
То же самое с
lambda:square = lambda x: x ** 2
А можно вообще не присваивать её переменной, а использовать сразу в выражении — и вот тут в игру вступает
map.---
### 2.
map: применяем функцию ко всем элементамmap(func, iterable) берёт каждый элемент из iterable и прогоняет его через func. Типичный пример:
nums = [1, 2, 3, 4]
result = map(lambda x: x * 10, nums)
print(list(result)) # [10, 20, 30, 40]
Обрати внимание:
map возвращает итератор, поэтому часто его оборачивают в list() или tuple().---
### 3. Создаём таплы с помощью
map и lambdaДопустим, у нас есть список чисел, и мы хотим получить кортеж пар
(число, его квадрат):nums = [1, 2, 3, 4, 5]
pairs = tuple(
map(lambda x: (x, x ** 2), nums)
)
print(pairs)
# ((1, 1), (2, 4), (3, 9), (4, 16), (5, 25))
Здесь важно:
-
lambda x: (x, x ** 2) возвращает кортеж из двух элементов.-
map(...) создаёт поток таких кортежей.-
tuple(...) собирает их в один большой кортеж.---
### 4. Комбинируем несколько итерируемых объектов
map может работать сразу с несколькими последовательностями. Например, создадим кортеж таплов из координат:xs = [0, 1, 2]
ys = [10, 11, 12]
points = tuple(
map(lambda x, y: (x, y), xs, ys)
)
print(points)
# ((0, 10), (1, 11), (2, 12))
Так можно элегантно “склеивать” данные без явных циклов.
---
### 5. Однострочные конвейеры преобразований
Связка
map + lambda хорошо работает как мини-конвейер обработки данных:raw_data = ["1", "2", "3", "4"]
processed = tuple(
map(lambda x: int(x) * 2, raw_data)
)
print(processed)
# (2, 4, 6, 8)
Считываем строки → сразу превращаем в числа → сразу умножаем.
---
### Когда это оправдано
- Нужно быстро преобразовать последовательность.
- Логика простая и умещается в одну строку.
- Нужен результат именно в виде кортежей (например, для неизменяемых данных или в качестве ключей словаря).
Если выражение становится громоздким и трудно читаемым — лучше вернуться к обычным функциям и циклам. Но для небольших преобразований
lambda + map + tuple даёт лаконичный и выразительный код, который отлично вписывается в стиль Python.👍2🔥1
Объединение и фильтрация данных с
Представьте, что у вас есть конвейер обработки данных. Вход — «сырые» списки, выход — аккуратный результат. В Python роль такого конвейера идеально играют функции
---
###
То же самое через
---
###
Комбинация с
Сначала отфильтровали положительные, потом возводим их в квадрат.
---
###
На основе
---
### Все вместе: мини-аналитика
Допустим, у нас есть имена, оценки и флаг «сдал экзамен» (True/False). Нужно оставить только тех, кто сдал, и взять их имена и удвоенные баллы (например, за бонус).
---
filter, map, zipПредставьте, что у вас есть конвейер обработки данных. Вход — «сырые» списки, выход — аккуратный результат. В Python роль такого конвейера идеально играют функции
filter, map и zip. Разберём, как их сочетать так, чтобы код был короче, понятнее и «питонистее».---
###
filter: оставляем только нужноеfilter(func, iterable) пропускает через себя элементы, оставляя только те, для которых func возвращает True.numbers = [10, -3, 0, 25, -7, 8]
def is_positive(x):
return x > 0
positive_numbers = list(filter(is_positive, numbers))
print(positive_numbers) # [10, 25, 8]
То же самое через
lambda:positive_numbers = list(filter(lambda x: x > 0, numbers))
---
###
map: трансформируем элементыmap(func, iterable) применяет функцию к каждому элементу.numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16]
Комбинация с
filter даёт уже мини-пайплайн:numbers = [-3, -1, 0, 1, 2, 3]
result = list(
map(
lambda x: x ** 2,
filter(lambda x: x > 0, numbers)
)
)
print(result) # [1, 4, 9]
Сначала отфильтровали положительные, потом возводим их в квадрат.
---
###
zip: объединяем несколько источников данныхzip склеивает элементы из нескольких итерируемых объектов по позициям.names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
paired = list(zip(names, scores))
print(paired) # [('Alice', 85), ('Bob', 92), ('Charlie', 78)]
На основе
zip удобно строить структуры данных:students = [
{"name": name, "score": score}
for name, score in zip(names, scores)
]
print(students)
# [{'name': 'Alice', 'score': 85}, ...]
---
### Все вместе: мини-аналитика
Допустим, у нас есть имена, оценки и флаг «сдал экзамен» (True/False). Нужно оставить только тех, кто сдал, и взять их имена и удвоенные баллы (например, за бонус).
names = ["Alice", "Bob", "Charlie", "Diana"]
scores = [85, 40, 73, 95]
passed = [True, False, True, True]
data = zip(names, scores, passed)
passed_transformed = list(
map(
lambda item: (item[0], item[1] * 2),
filter(lambda item: item[2], data)
)
)
print(passed_transformed)
# [('Alice', 170), ('Charlie', 146), ('Diana', 190)]
zip объединяет разрозненные списки в единый поток кортежей, filter выбрасывает тех, кто не сдал, map меняет формат результата и пересчитывает баллы.---
filter, map и zip — это кирпичики для построения аккуратных конвейеров обработки данных. В связке они позволяют писать код, который одновременно лаконичен и легко читается как последовательность шагов над данными.👍3