Модули в Python
Пока каждая ваша программа помещалась в один файл, и этого хватало. Но однажды вы напишете функцию, которая пригодится и в следующей задаче, а перенести её туда получится только копированием. Скопировали в три скрипта, нашли ошибку — правите в трёх местах.
Значит, нужен способ держать код в отдельном файле и подключать оттуда только нужное. Такой файл называется модулем.
Вы уже пользуетесь модулями
Строка import math встречалась вам в главах про библиотеки. Посмотрим внимательнее, что происходит после неё.
Python 3.13import math print(math.sqrt(144))12.0print(type(math))<class 'module'>
import не вставляет текст чужого файла в ваш. Он создаёт объект-модуль и кладёт его в переменную с именем math. Дальше math.sqrt — обычное обращение к атрибуту объекта, точно такое же, как "строка".upper().
Создаём свой модуль
Теперь сделаем такой файл сами. Пусть у нас есть небольшой скрипт, который считает цены: прибавляет НДС и применяет скидки. Сам расчёт положим в prices.py, а в main.py оставим только вывод результатов:
1import prices2 3print(prices.with_vat(100)) # 120.04print(prices.discount(1000, 15)) # 850.05print(prices.VAT) # 0.26 main.py пишет import prices, и Python находит prices.py в той же папке. Имя модуля берётся из имени файла: убираем .py, получаем prices. Этого достаточно, чтобы импорт заработал.
Раз имя модуля — это имя файла, называйте файлы в snake_case: user_interface.py, а не UserInterface.py. И не random.py: файл, названный как модуль стандартной библиотеки, перекроет настоящий модуль.
Код модуля выполняется ровно один раз
При импорте Python выполняет файл сверху донизу. В boot.py ниже print стоит на верхнем уровне, не внутри функции, поэтому сработает при импорте. Импортируем этот модуль двумя строками подряд:
1import boot2import boot3 4print("а строк с import было две")5 boot.py выполняется а строк с import было две
Хотя строк с import было две, файл выполнился один раз: готовые модули Python запоминает и при повторном импорте отдаёт тот же объект. Отсюда практический вывод: на верхнем уровне модуля держат определения, а не действия — всё, что там написано, выполнится при первом же импорте, даже если ни одна функция оттуда не понадобится.
from ... import: имя переезжает к вам
Писать prices. перед каждым вызовом надоедает. Форма from ... import забирает из модуля конкретное имя и кладёт его прямо в вашу программу. В примере ниже обе формы импорта стоят рядом нарочно, чтобы в последней строке сравнить результат — в обычном коде так не пишут.
1import prices2from prices import with_vat3 4print(with_vat(100)) # 120.05print(with_vat is prices.with_vat) # True6 Последняя строка — самое важное здесь. Никакой копии функции не появилось: with_vat и prices.with_vat — два имени одного объекта. from ... import не «другой способ импорта», а дополнительное действие: сначала модуль импортируется целиком (со всем своим кодом), потом одно из его имён копируется в ваше пространство имён.
Итого у вас три формы, и выбирают между ними так:
-
Функций из модуля нужно много, или важно видеть, откуда взялось имя — оставьте префикс:
Python 3.13import prices print(prices.with_vat(100)) -
Нужны две-три функции и вызываются они часто — заберите их по именам, код станет короче:
Python 3.13from prices import with_vat, discount print(with_vat(100)) -
Имя модуля длинное или уже занято вашей переменной — подключите его под коротким именем:
Python 3.13import prices as p print(p.with_vat(100))
Последняя форма — та самая причина, по которой пишут import pandas as pd.
Как отличить запуск от импорта
Как мы видели, при импорте выполняется весь код модуля. Значит, код внутри prices.py отработает в обоих случаях:
python prices.py # запускаем сам модуль python main.py # запускаем программу, которая его импортирует
Но иногда код нужен только при прямом запуске файла. Например, проверка «а верно ли считают функции»: автору она удобна, а тому, кто импортирует модуль, только мешает.
Отличить одно от другого позволяет переменная __name__, она есть у каждого модуля. При импорте в ней лежит имя модуля, здесь это "prices". А у файла, который запустили напрямую, там всегда "__main__". Поэтому такое условие истинно только при прямом запуске:
Python 3.13if __name__ == "__main__": print("проверка:", with_vat(100))
В prices.py ниже эта проверка стоит в самом конце, а main.py на соседней вкладке просто импортирует модуль:
1"""Расчёт цен: НДС и скидки."""2 3VAT = 0.24 5 6def with_vat(price):7 """Цена с НДС."""8 return round(price * (1 + VAT), 2)9 10 11def discount(price, percent):12 """Цена после скидки в процентах."""13 return round(price * (1 - percent / 100), 2)14 15 16if __name__ == "__main__":17 print("проверка:", with_vat(100))18 итог: 120.0
Запустили main.py — в выводе только его собственная строка: __name__ внутри prices.py равен "prices", условие ложно, проверка промолчала. А при прямом запуске модуля напечаталось бы проверка: 120.0.
Так один файл совмещает две роли: набор функций для чужого кода и самостоятельная программа. В этот блок кладут всё, что не должно случаться при импорте: запуск программы, разбор аргументов командной строки, проверки вроде нашей.
