Генерация PDF документов для упражнений по программированию на Python

Раздел: Образование -> Учебные материалы

Введение в создание PDF с задачами по Python

Учебные материалы часто требуют распространения в формате PDF, сохраняющем структуру и шрифты. Рассмотрены способы автоматической генерации PDF с условиями задач по Python с помощью различных библиотек.

Как создать PDF с задачами, используя библиотеку ReportLab?

Цель: Получить гибко настраиваемый PDF с текстом задач, возможностью вставки формул и таблиц.

Решение: Библиотека ReportLab предоставляет низкоуровневый доступ к построению страниц. Для работы с кириллицей требуется регистрация шрифта.

from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont('DejaVu', 'DejaVuSans.ttf'))

c = canvas.Canvas('zadachi.pdf', pagesize=A4)
width, height = A4

c.setFont('DejaVu', 14)
c.drawString(50, height - 50, 'Задача 1. Сумма чисел')
c.setFont('DejaVu', 12)
c.drawString(50, height - 80, 'Напишите функцию, которая принимает список чисел и возвращает их сумму.')
c.save()

задачи python pdf (задачи по python в формате pdf)

Пояснение: После регистрации шрифта DejaVuSans (скачайте его) кириллица отображается корректно. Canvas рисует строки в абсолютных координатах.

Проблема: Шрифт не найден. Решение: указать полный путь к файлу .ttf или использовать встроенный шрифт Helvetica (не поддерживает кириллицу).

Как упростить создание PDF с задачами через библиотеку FPDF2?

Цель: Быстрое прототипирование PDF с автоматическим переносом строк.

Решение: FPDF2 предоставляет класс FPDF с методами add_font, cell, multi_cell.

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.add_font('DejaVu', '', 'DejaVuSans.ttf', uni=True)
pdf.set_font('DejaVu', size=14)
pdf.cell(200, 10, text='Задача 2. Факториал', new_x='LMARGIN', new_y='NEXT')
pdf.set_font('DejaVu', size=12)
pdf.multi_cell(0, 10, text='Вычислите факториал числа, введённого пользователем.')
pdf.output('zadachi_fpdf2.pdf')

уроки и задачи python (уроки и задачи по python)

Пояснение: multi_cell автоматически разбивает текст на строки. Преимущество: не нужно вычислять координаты вручную.

Ошибка: Кириллица отображается как кракозябры. Решение: при добавлении шрифта обязательно указать uni=True и использовать .ttf файл с поддержкой Unicode.

Как создать PDF из HTML шаблона с задачами с помощью WeasyPrint?

Цель: Использовать привычный HTML/CSS для оформления, затем преобразовать в PDF.

Решение: Библиотека WeasyPrint преобразует HTML и CSS в PDF.

from weasyprint import HTML

html_content = '''
<h2>Задача 3. Чётные числа</h2>
<p>Выведите все чётные числа от 1 до 100 в одну строку.</p>
'''
HTML(string=html_content).write_pdf('zadachi_weasy.pdf')

Пояснение: Можно подгружать CSS из файла или использовать встроенные стили. Случай использования: когда дизайн сложный (таблицы, списки, цвета).

Проблема: Неправильное отображение кириллицы. Решение: указать кодировку в HTML <meta charset='utf-8'> и использовать шрифты, поддерживающие кириллицу (например, через @font-face).

Расширенные примеры создания PDF с задачами по Python

Многостраничный PDF с нумерацией страниц (ReportLab)

Создание документа с несколькими десятками задач, автоматическая нумерация страниц и колонтитулы.

Пример
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont('DejaVu', 'DejaVuSans.ttf'))

def draw_page(c, page_num):
    c.setFont('DejaVu', 8)
    c.drawRightString(200*mm, 10*mm, f'Страница {page_num}')
    c.drawString(20*mm, 10*mm, 'Курс Python. Задачи')

c = canvas.Canvas('many_tasks.pdf', pagesize=A4)
width, height = A4
tasks = ['Задача {}: ...'.format(i) for i in range(1, 31)]

page_num = 1
y = height - 30

for task in tasks:
    if y < 50:
        draw_page(c, page_num)
        c.showPage()
        page_num += 1
        y = height - 30
    c.setFont('DejaVu', 12)
    c.drawString(50, y, task)
    y -= 20

# последняя страница
if y < height - 30:
    draw_page(c, page_num)
    c.save()
Создан PDF файл 'many_tasks.pdf' с 2 страницами, содержащими 30 задач, нумерация страниц и колонтитулы.

Добавление таблицы с условиями и ответами (FPDF2)

Формирование таблицы, где в каждой строке номер задачи, условие и правильный ответ.

Пример
from fpdf import FPDF

class PDF(FPDF):
    def header(self):
        self.set_font('DejaVu', 'B', 12)
        self.cell(0, 10, 'Таблица задач', align='C', new_x='LMARGIN', new_y='NEXT')

pdf = PDF()
pdf.add_page()
pdf.add_font('DejaVu', '', 'DejaVuSans.ttf', uni=True)
pdf.add_font('DejaVu', 'B', 'DejaVuSans-Bold.ttf', uni=True)

# заголовки
pdf.set_font('DejaVu', 'B', 10)
pdf.cell(20, 10, '№', border=1)
pdf.cell(80, 10, 'Условие', border=1)
pdf.cell(50, 10, 'Ответ', border=1, new_x='LMARGIN', new_y='NEXT')

# данные
pdf.set_font('DejaVu', '', 10)
tasks_data = [
    (1, 'Найти сумму 1+2+3', '6'),
    (2, 'Проверить чётность числа 7', 'False'),
    (3, 'Вывести 'Hello, World!'', 'Hello, World!')
]
for num, cond, ans in tasks_data:
    pdf.cell(20, 10, str(num), border=1)
    pdf.cell(80, 10, cond, border=1)
    pdf.cell(50, 10, ans, border=1, new_x='LMARGIN', new_y='NEXT')

pdf.output('tasks_table.pdf')
PDF с таблицей из 3 строк задач, каждая ячейка имеет границы.

Генерация PDF с использованием шаблонов Jinja2 и WeasyPrint

Динамическое создание HTML из шаблона, затем преобразование в PDF.

Пример
from jinja2 import Template
from weasyprint import HTML

template = Template('''
<!DOCTYPE html>
<html>
<head><meta charset='utf-8'></head>
<body>
<h1>Задачи по Python</h1>
{% for task in tasks %}
<div class='task'>
    <h3>Задача {{ task.num }}</h3>
    <p>{{ task.text }}</p>
</div>
{% endfor %}
</body>
</html>
''')

tasks = [
    {'num': 1, 'text': 'Напишите программу для перевода градусов Цельсия в Фаренгейты.'},
    {'num': 2, 'text': 'Создайте класс Car с методами start и stop.'}
]
html = template.render(tasks=tasks)
HTML(string=html).write_pdf('tasks_jinja_weasy.pdf')
Сформирован PDF с HTML стилизацией, заголовками и отступами, автоматически подставляются данные из словаря.

Извлечение задач из существующего PDF с помощью pdfplumber

Обратная задача: прочитать PDF с условиями и обработать их. Пример извлечения текста всех страниц.

Пример
import pdfplumber

with pdfplumber.open('tasks.pdf') as pdf:
    for page_num, page in enumerate(pdf.pages, start=1):
        text = page.extract_text()
        print(f'Страница {page_num}:')
        print(text[:200])  # первые 200 символов
Страница 1:
Задача 1. Сумма чисел
Напишите функцию, которая принимает список чисел и возвращает их сумму.
...

Примечание: pdfplumber хорошо работает с текстовыми PDF, но не подходит для отсканированных документов.

Задачи по Python в формате PDF - comments

En
задачи python pdf (python)