Модули и упаковка — Примеры

Пример 1 — Импорт файла запускает программу

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

import json

def load(path):
    with open(path) as handle:
        return json.load(handle)

def build_index(rows):
    return {row["id"]: row for row in rows}

rows = load("rows.json")
index = build_index(rows)
print(f"indexed {len(rows)} rows")
run_report(index)

Решение

import json

def load(path):
    with open(path) as handle:
        return json.load(handle)

def build_index(rows):
    return {row["id"]: row for row in rows}

def main():
    rows = load("rows.json")
    index = build_index(rows)
    print(f"indexed {len(rows)} rows")
    return run_report(index)

if __name__ == "__main__":
    main()

Операторы верхнего уровня модуля выполняются при первом импорте и только тогда, поэтому один импорт уже печатал и индексировал; под защитой main работа идёт только при прямом запуске файла, а функции становятся вызываемыми из теста. Ошибка — перенести работу в функцию, но оставить вызов вне защиты: тогда импорт всё ещё запускает программу. Держите защиту и верхний уровень свободными от побочных эффектов.

Пример 2 — Два проекта делят один интерпретатор

Установка библиотеки для второго проекта обновила копию, на которую опирается первый, и теперь первый падает при импорте, а в readme записано только то, что автор вспомнил. Получите окружение и записанный список, по которому всё сможет пересобрать другой человек.

# report.py — работал на машине автора
from <dependency> import read_rows

Решение

python -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m pip freeze > requirements.lock

# теперь каждый проект собирается по своему lock-файлу, а не по памяти

Виртуальное окружение даёт каждому проекту собственный интерпретатор и набор установленных пакетов, поэтому обновление для одного не задевает другой, а зафиксированный список записывает версии, по которым пересобирает коллега. Однако ошибка — установить в тот интерпретатор, который оказался активным, и записать список зависимостей по памяти. Подставьте в пример выше имя своей зависимости вместо заглушки: важен не пакет, а два записанных файла.