Анатомия файла
импорты, константы, определения, точка входа
Что это
Почти любой файл с кодом устроен одинаково: сверху то, что нужно для работы, в середине определения, внизу запуск. Зная эти четыре зоны, в незнакомом файле ориентируешься за полминуты, не читая его целиком.
Порядок не случаен: он совпадает с порядком, в котором код выполняется при импорте файла.
Как выглядит в коде
Вот файл целиком — все четыре зоны по порядку:
"""Бот напоминаний. Один файл целиком."""
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__":— «если файл запустили напрямую».Незнакомый файл читай с конца, от точки входа.
Код вне функций выполняется при импорте — почти всегда ошибка.