$ sudo teach IT
Модуль 7 · Инструменты Python · Урок 7.1

Модули и import

Как подключать к программе уже готовый код Python, разбирать его на части, собирать свой собственный файл-инструмент и отличать запуск программы от её импорта

Теория~30 минутНовичокimportfrom ... importasсвой модуль

Всё, что вы писали до сих пор, помещалось в один файл — это удобно, пока программа маленькая. Но представьте программу для интернет-магазина: код для денег, код для дат доставки, код для статистики по продажам. Если тащить всё в один файл, он превратится в свалку из тысяч строк. А часть этой работы — округление денег, подсчёт среднего — уже давно написана и проверена другими программистами. Модули решают обе проблемы разом: позволяют разложить свой код по отдельным файлам и подключать чужой готовый код, не переписывая его заново.

Что такое модуль

Представьте ящик с инструментами. Молоток, отвёртка, рулетка — каждый лежит в своей ячейке, и вы берёте только то, что нужно для текущей задачи, а не вываливаете весь ящик на стол. Программисты по всему миру уже написали огромное количество готовых "инструментов" на Python: функции для математики, для работы с датами, для генерации случайных чисел. Все они разложены по отдельным файлам, и вы можете взять из такого файла только то, что нужно вам прямо сейчас.

Официальный термин для такого файла-инструмента — модуль. Модуль — это обычный файл с расширением .py, в котором лежат функции, переменные или другой код. Когда вы подключаете модуль к своей программе, все функции и переменные из него становятся вам доступны. Python поставляется с большим набором готовых модулей — их называют стандартной библиотекой, о ней поговорим чуть дальше. Кроме них, вы сами можете написать модуль и подключить его в другом своём файле.

import: подключаем модуль целиком

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

Эта команда называется import (в переводе — "ввезти", "подключить"). После import указывается имя модуля, а обратиться к чему-то внутри него можно через точку: имя_модуля.имя_функции. Такая запись через точку называется точечной нотацией, и вы уже встречали её раньше, когда вызывали методы строк вроде text.upper() — принцип тот же самый.

import math

print(math.sqrt(25))
print(math.pi)

Разберём построчно:

  • import math — подключаем модуль math из стандартной библиотеки. Он хранит математические функции и константы: корень, степень, число пи и другие. Строка ничего не выводит, она только делает модуль доступным дальше по коду.
  • print(math.sqrt(25)) — обращаемся к функции sqrt (квадратный корень) внутри модуля math через точку и вызываем её со значением 25. Выведется 5.0.
  • print(math.pi) — pi здесь не функция, а переменная-константа внутри модуля math: число π. Скобок нет, потому что мы не вызываем функцию, а просто читаем значение. Выведется 3.141592653589793.

Почему через точку, а не просто sqrt(25)? Так Python сразу понимает, откуda взялась функция, и разные модули не путают друг друга: если бы в двух разных ящиках лежали инструменты с одинаковым названием, точка с именем модуля показывает, из какого именно ящика вы его достали.

from ... import: берём только нужное

Иногда из целого ящика вам нужна одна-единственная отвёртка, и таскать за собой весь ящик неудобно — хочется положить её прямо в карман, чтобы обращаться к ней по имени напрямую.

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

from math import sqrt, pi

print(sqrt(25))
print(pi)

Разберём построчно:

  • from math import sqrt, pi — из модуля math достаём только функцию sqrt и константу pi, перечислив их через запятую. Остальное содержимое модуля math при этом не подключается вовсе.
  • print(sqrt(25)) — теперь sqrt используется без math. впереди, потому что мы забрали именно эту функцию себе "в карман". Выведется 5.0, как и раньше.
  • print(pi) — то же самое с константой: обращаемся к ней напрямую по имени. Выведется 3.141592653589793.

Ловушка формы from ... import: если вы заберёте из разных модулей две функции с одинаковым именем, вторая незаметно перекроет первую — Python не предупредит об этом. У обычного import модуль такой проблемы нет, потому что имя модуля перед точкой всегда показывает источник. Поэтому from ... import удобен для одной-двух хорошо знакомых вещей, а для модуля целиком чаще используют обычный import.

as: даём модулю удобное имя

Названия некоторых модулей длинные, а использовать их в коде приходится часто — писать длинное имя перед точкой каждый раз утомительно. Это как подписать длинное официальное название фирмы-производителя коротким словом, которое удобно именно вам.

Для этого в Python есть ключевое слово as ("как"): оно ставится после имени модуля и задаёт для него короткий псевдоним — новое имя, под которым модуль будет доступен дальше по коду. Так же можно переименовать и отдельную функцию при импорте через from ... import ... as ....

import statistics as stats

numbers = [4, 8, 15, 16, 23]
print(stats.mean(numbers))

Разберём построчно:

  • import statistics as stats — подключаем модуль statistics (статистика), но даём ему короткий псевдоним stats. Дальше по коду обращаться к модулю нужно именно через stats, а не через полное имя statistics.
  • numbers = [4, 8, 15, 16, 23] — обычный список чисел, с которым мы уже умеем работать.
  • print(stats.mean(numbers)) — вызываем функцию mean (среднее арифметическое) из модуля statistics, но обращаемся к нему через псевдоним stats. Выведется 13.2 — среднее значение пяти чисел.

Псевдоним — это обычное переименование: после строки с as stats имени statistics для программы как будто больше не существует, есть только stats.

Стандартная библиотека Python

Когда вы устанавливаете Python, вместе с ним сразу попадает большой набор готовых модулей — их не нужно отдельно скачивать, они всегда под рукой. Это как купить ящик с инструментами, в котором уже лежит стартовый набор для базовых задач.

Такой набор официально называется стандартной библиотекой (standard library). В ней сотни модулей на любой случай: от математики до работы с файлами. Полезно заранее знать, какие инструменты вообще есть в этом ящике.

mathматематические функции и константы: корень, степень, синус, число π
statisticsсреднее, медиана и другие статистические расчёты по числам
randomслучайные числа и случайный выбор из списка — отдельный урок впереди
datetimeработа с датами и временем — тоже разберём отдельно
os, sysвзаимодействие с операционной системой и настройками самого Python

Кроме стандартной библиотеки существуют модули, которые пишут другие программисты и выкладывают в открытый доступ отдельно от Python — их называют сторонними библиотеками, их нужно ставить дополнительно. Как это делать, вы узнаете в отдельном уроке. А сегодняшний урок — про то, как вообще устроено подключение любого модуля.

Создаём свой модуль

Модулем может быть не только чужой готовый файл — точно так же модулем становится любой ваш собственный файл с расширением .py, если вы подключите его из другого файла. Никакой специальной команды не нужно: как только вы пишете функции в отдельном файле, он уже готов к тому, чтобы его импортировали.

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

# файл helpers.py
def square(n):
    return n * n

def is_even(n):
    return n % 2 == 0
# файл main.py
import helpers

print(helpers.square(5))
print(helpers.is_even(5))

Разберём построчно:

  • helpers.py — обычный файл с двумя функциями, ничем не отличается от любого файла, который вы писали раньше. Название файла без расширения .py и станет именем модуля.
  • import helpers в файле main.py — подключаем файл helpers.py так же, как подключали бы math. Python ищет файл helpers.py в той же папке, что и main.py.
  • print(helpers.square(5)) — вызываем функцию square из модуля helpers через точку, ровно так же, как math.sqrt(...). Выведется 25.
  • print(helpers.is_even(5)) — вызываем вторую функцию. Выведется False, потому что 5 нечётное.

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

if __name__ == "__main__": запуск или импорт?

Когда вы импортируете модуль, Python не просто "заглядывает" в файл за нужной функцией — он выполняет этот файл целиком, сверху вниз, один раз. Обычно это не проблема: функции просто объявляются и ничего не печатают. Но что если в файле helpers.py для проверки была строка print(square(5))? Тогда при каждом импорте этого модуля у вас неожиданно печаталось бы число 25 — хотя вы всего лишь хотели воспользоваться функцией.

Чтобы этого избежать, Python даёт каждому файлу встроенную переменную __name__. Если файл запущен напрямую (python main.py), в этой переменной автоматически оказывается строка "__main__". А если тот же файл подключён через import из другого файла, в __name__ будет храниться имя самого модуля. Проверяя условием if __name__ == "__main__":, вы отделяете код для прямого запуска от того, что должно работать и при импорте.

# файл helpers.py
def square(n):
    return n * n

if __name__ == "__main__":
    print(square(5))

Разберём построчно:

  • def square(n): return n * n — функция объявляется как обычно, она выполнится в любом случае: и при прямом запуске, и при импорте.
  • if __name__ == "__main__": — проверяем, запущен ли этот файл напрямую. Если да — переменная __name__ равна строке "__main__", и условие истинно.
  • print(square(5)) внутри if — эта строка выполнится, только если файл helpers.py запустили напрямую командой python helpers.py. Если же кто-то напишет import helpers в другом файле, эта строка выполнена не будет, и никакого лишнего вывода не появится — станет доступна только сама функция square.

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

Частые ошибки

Обращение к функции без имени модуля после import

import math, а затем вызов sqrt(25) без math. впереди — вызовет NameError: name 'sqrt' is not defined. После обычного import нужно всегда обращаться через точку: math.sqrt(25).

Опечатка в имени модуля или функции

import mathh вызовет ModuleNotFoundError: No module named 'mathh', а math.squareroot(25) вызовет AttributeError, потому что такой функции в модуле нет — правильное имя sqrt.

Использование псевдонима без as, а по памяти

После import statistics as stats имя statistics для кода больше не существует — обращение к statistics.mean(...) вызовет NameError. Работать нужно только через stats.

Своё имя файла совпадает с именем стандартного модуля

Если назвать свой файл math.py и лежит он в той же папке, Python при import math найдёт именно ваш файл, а не встроенный модуль — и настоящий math.sqrt станет недоступен. Не называйте свои файлы именами модулей стандартной библиотеки.

Что важно запомнить

  • Модуль — это файл .py с функциями, переменными или другим кодом, который можно подключить к своей программе.
  • import имя_модуля подключает модуль целиком, обращаться к его содержимому нужно через точку: имя_модуля.имя_функции.
  • from имя_модуля import имя1, имя2 достаёт конкретные имена и делает их доступными напрямую, без точки, но может незаметно перекрыть одинаковые имена из разных модулей.
  • as задаёт короткий псевдоним модулю или имени: после него обращаться нужно только по новому имени.
  • Стандартная библиотека — набор готовых модулей, которые устанавливаются вместе с Python и не требуют отдельной загрузки.
  • Любой ваш файл .py сам становится модулем, как только его подключают через import из другого файла.
  • __name__ равен "__main__" только при прямом запуске файла — условие if __name__ == "__main__": отделяет код для прямого запуска от кода, который должен работать и при импорте.

Проверьте себя

7 вопросов

Среднее и корень

В переменной numbers дан список чисел. Используя модули math и statistics из стандартной библиотеки, вычислите:

  • rounded_mean — среднее арифметическое чисел списка (функция mean модуля statistics), округлённое до целого встроенной функцией round;
  • root — квадратный корень из максимального числа списка (функция sqrt модуля math, максимум ищите встроенной функцией max).

Например, для numbers = [4, 9, 16] среднее равно 9.666..., округлённое — 10, а корень из максимума (16) — 4.0.

Соберите инструменты по имени

Premium