Урок 84. MongoDB и Python. Модули

📁 Блок: Базы данных и модули ⏱️ Время изучения: ~90 мин 🎯 Сложность: Средняя
#close #find #sort #list #in #import #from

⚡ Кратко: решения

Ответы на викторину и разбор практических задач. Обратите внимание на:

  • курсор, который возвращает find();
  • правильное использование фильтров и проекций;
  • обработку ошибок через pymongo.errors;
  • использование if __name__ == "__main__" в модулях.

✅ Решения заданий

Викторина

1

Способы добавления данных

Ответ: a, b — insert_one() и insert_many().

Методов add_documents() и create_one() в PyMongo нет.

2

Тип возвращаемого значения find()

Ответ: b — курсор (итератор).

Метод find() не возвращает список. Чтобы получить список, нужно вызвать list(cursor).

3

Сопоставь термин и определение

Ответ: 1-b, 2-a, 3-d, 4-c.

  • Модуль — любой .py файл.
  • Пакет — папка с модулями и __init__.py.
  • __pycache__ — папка с байт-кодом.
  • __init__.py — файл, обозначающий папку как пакет.
4

Назначение .pyc

Ответ: b — является скомпилированной версией .py файла.

Байт-код ускоряет повторный импорт, но программу без Python он запустить не может.

Практические задания

Задание 1. Подключение и проверка

Файл: task01_connect.py

from pymongo import MongoClient

client = MongoClient("mongodb://...")

try:
    client.admin.command("ping")
    print("Connection successful!")
finally:
    client.close()

Пояснение: метод command("ping") проверяет, доступен ли сервер. Соединение закрывается в finally, чтобы оно не осталось открытым при ошибке.

Задание 2. Добавление и вывод товаров

Файл: task02_insert.py

from pymongo import MongoClient

client = MongoClient("mongodb://...")
products = client["ich_edit"]["products_training"]

items = [
    {"name": "Pen", "price": 1.50, "stock": 300},
    {"name": "Pencil", "price": 0.99, "stock": 500},
    {"name": "Notebook", "price": 5.99, "stock": 120},
]

result = products.insert_many(items)
print("Inserted IDs:", result.inserted_ids)

client.close()

Пояснение: insert_many() принимает список словарей и возвращает объект с перечнем _id всех вставленных документов.

Задание 3. Поиск и проекция

Файл: task03_find.py

from pymongo import MongoClient

client = MongoClient("mongodb://...")
products = client["ich_edit"]["products_training"]

for doc in products.find(
    {"price": {"$lt": 5}},
    {"_id": 0, "name": 1, "price": 1}
).sort("price", 1):
    print(doc)

client.close()

Пояснение: первый аргумент find() — фильтр, второй — проекция. sort("price", 1) сортирует по возрастанию цены.

Задание 4. Обновление и удаление

Файл: task04_update_delete.py

from pymongo import MongoClient

client = MongoClient("mongodb://...")
products = client["ich_edit"]["products_training"]

update_result = products.update_many(
    {},
    {"$mul": {"price": 1.1}}
)
print("Updated:", update_result.modified_count)

delete_result = products.delete_many({"stock": 0})
print("Deleted:", delete_result.deleted_count)

client.close()

Пояснение: оператор $mul умножает числовое поле. В лекции рассматривался $inc, но для процентов удобнее $mul. Увеличение на 10% эквивалентно умножению на 1.1.

⚠️ Проверить по документации: оператор $mul выходит за рамки исходной лекции. Его можно заменить на $set с предварительным вычислением новой цены в Python или на $inc с добавлением 10% от текущей цены, если цены целочисленные.

Задание 5. Обработка ошибок

Файл: task05_errors.py

from pymongo import MongoClient, errors

client = MongoClient(
    "mongodb://ich_editor:wrong_pass@mongo.itcareerhub.de/?authSource=ich_edit"
)

try:
    db = client["ich_edit"]
    products = db["products"]
    products.insert_one({"name": "Test"})
except errors.ConnectionFailure:
    print("Ошибка подключения к MongoDB")
except errors.OperationFailure:
    print("Ошибка авторизации или запроса")
except errors.PyMongoError as e:
    print("Общая ошибка pymongo:", e)
finally:
    client.close()

Пояснение: конкретные исключения перехватываются до общего PyMongoError, потому что обработчики проверяются сверху вниз.

Задание 6. Создание модуля и пакета

Файл: string_utils.py

def count_words(text):
    return len(text.split())


def reverse(text):
    return text[::-1]


if __name__ == "__main__":
    sample = "Hello world"
    print("Words:", count_words(sample))
    print("Reversed:", reverse(sample))

Файл: tools/__init__.py

from .string_utils import count_words, reverse

Файл: main.py

import tools

if __name__ == "__main__":
    text = "Learn Python modules"
    print(tools.count_words(text))
    print(tools.reverse(text))

Пояснение: модуль string_utils можно запускать напрямую для тестирования. Пакет tools предоставляет функции через __init__.py, поэтому в main.py достаточно импортировать сам пакет.