Программирование с ИИ
ENRU
2.2

Анатомия файла

импорты, константы, определения, точка входа

Что это

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

Порядок не случаен: он совпадает с порядком, в котором код выполняется при импорте файла.

Как выглядит в коде

Схема из книги — будет перерисована для сайта
Четыре зоны файла. Сверху вниз — в том же порядке, в каком код выполняется при запуске.

Вот файл целиком — все четыре зоны по порядку:

"""Бот напоминаний. Один файл целиком."""
import os
import sqlite3

DB_PATH = os.environ.get("DB_PATH", "reminders.db")
MAX_TEXT = 200


def get_conn() -> sqlite3.Connection:
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn


def add_reminder(user_id: int, text: str) -> int:
    if len(text) > MAX_TEXT:
        raise ValueError(f"текст длиннее {MAX_TEXT} символов")
    with get_conn() as conn:
        cur = conn.execute(
            "INSERT INTO reminders (user_id, text) VALUES (?, ?)",
            (user_id, text),
        )
        return cur.lastrowid


def main() -> None:
    ...


if __name__ == "__main__":
    main()

Что читать в каждой зоне

Импорты отвечают на вопрос «от чего зависит этот файл». import sqlite3 — работа с базой. Увидел import requests — файл ходит в сеть. Это первое, что стоит прочитать: по импортам понятно, чем файл вообще занимается.

Константы — это настройки, вынесенные наверх, чтобы их было легко найти. DB_PATH = os.environ.get("DB_PATH", "reminders.db") читается так: взять значение из переменной окружения, а если её нет — использовать reminders.db.

Определения — самая длинная зона и самая безобидная. Ключевое: def только описывает функцию, но не запускает её. Файл можно импортировать, и ни одна строка внутри def не выполнится.

Точка входа — строки if __name__ == "__main__":. Читается так: «если этот файл запустили напрямую, а не импортировали — выполни то, что ниже».

Как сказать ИИ

Запрос
Разбери этот файл по зонам: что в импортах, какие константы,
какие функции определены и что выполняется при запуске.
Коротко, по одной строке на пункт.

Для незнакомого проекта полезнее другой вопрос:

Запрос
С какой функции в этом файле начать чтение, чтобы понять,
что он делает? Не объясняй весь файл, просто скажи,
с чего начать и почему.

На что смотреть

Код вне функций. Всё, что написано на верхнем уровне и не является импортом, константой или определением, выполнится при импорте файла. Строка conn = sqlite3.connect(DB_PATH) вне функции означает, что база откроется от самого факта импорта, — и это почти всегда ошибка.

Нет точки входа, а файл запускают. Если if __name__ == "__main__": отсутствует, но файл предполагается запускать, где-то внизу найдётся голый вызов — и он сработает при импорте тоже.

Константы, которые не константы. Имя заглавными буквами обещает, что значение не меняется. Если ИИ написал MAX_TEXT = 200, а потом где-то MAX_TEXT = get_limit(), это сбивает с толку всех, включая следующего ИИ.

Секреты в константах. TOKEN = "123456:ABC-DEF" прямо в файле — токен попадёт в git и останется в истории навсегда. Правильно — из переменной окружения (статья 5.7).

Шпаргалка

  • Четыре зоны: импорты · константы · определения · точка входа.

  • Импорты читай первыми: по ним понятно, чем файл занимается.

  • def только описывает функцию, не выполняет её.

  • if __name__ == "__main__": — «если файл запустили напрямую».

  • Незнакомый файл читай с конца, от точки входа.

  • Код вне функций выполняется при импорте — почти всегда ошибка.