На этом шаге мы рассмотрим создание и особенности подключения созданных модулей, а также ряд полезных функций.
Все содержимое импортированного модуля доступно только через идентификатор, указанный в инструкции import. Это означает, что любая глобальная переменная на самом деле является глобальной переменной модуля. По этой причине модули часто используются как пространства имен. Для примера создадим модуль под названием tests.py, в котором определим переменную х:
# Содержимое модуля tests.py # -*- coding: utf-8 -*- x = 50
В основной программе также определим переменную x, но с другим значением. Затем подключим файл tests.py и выведем значения переменных:
# Содержимое основной программы # -*- coding: utf-8 -*- import tests # Подключаем файл tests,ру x = 22 print (tests.x) # Значение переменной х внутри модуля print(x) # Значение переменной х в основной программе input()
Оба файла размещаем в одной папке, а затем запускаем файл с основной программой с помощью двойного щелчка на значке файла.
Рис.1. Результат работы приложения
Как видно из результата, никакого конфликта имен нет, поскольку одноименные переменные расположены в разных пространствах имен.
Как говорилось на шаге 2, перед собственно выполнением каждый модуль Python компилируется, преобразуясь в особое внутреннее представление (байт-код), - это делается для ускорения выполнения кода. Файлы с откомпилированным кодом хранятся в папке __pycache__, автоматически создающейся в папке, где находится сам файл с исходным, неоткомпилированным кодом модуля, и имеют имена вида <имя файла с исходным кодом>.cpython-<nepвые две цифры номера версии Python>.pyc. Так, при запуске на исполнение нашего файла tests.py откомпилированный код будет сохранен в файле tests.cpython-34.pyc.
Следует заметить, что для импортирования модуля достаточно иметь только файл с откомпилированным кодом, файл с исходным кодом в этом случае не нужен. Для примера переименуйте файл tests.ру (например, в tests1.py), скопируйте файл tests.cpython-34.pyc из папки __pycache__ в папку с основной программой и переименуйте его в tests.pyc, а затем запустите основную программу. Программа будет нормально выполняться. Таким образом, чтобы скрыть исходный код модулей, можно поставлять программу клиентам только с файлами, имеющими расширение рус.
Существует еще одно обстоятельство, на которое следует обратить особое внимание. Импортирование модуля выполняется только при первом вызове инструкции import (или from, речь о которой пойдет в следующем шаге). При каждом вызове инструкции import проверяется наличие объекта модуля в словаре modules из модуля sys. Если ссылка на модуль находится в этом словаре, то модуль повторно импортироваться не будет. Для примера выведем ключи словаря modules, предварительно отсортировав их.
# Вывод ключей словаря modules # -*- coding: utf-8 -*- import tests, sys # Подключаем модули tests и sys print(sorted(sys.modules.keys())) input()
Результат работы приложения изображен на рисунке 2.
Рис.2. Результат работы приложения
Инструкция import требует явного указания объекта модуля. Так, нельзя передать название модуля в виде строки. Чтобы подключить модуль, название которого создается динамически в зависимости от определенных условий, следует воспользоваться функцией __import__(). Для примера подключим модуль tests.py с помощью функции __import__().
# Использование функции __import__() # -*- coding: utf-8 -*- s = "test" + "s" # Динамическое создание названия модуля m = __import__(s) # Подключение модуля tests print(m.x) # Вывод значения атрибута х. Выведет: 50 input ()
Получить список всех идентификаторов внутри модуля позволяет функция dir(). Кроме того, можно воспользоваться словарем __diсt__, который содержит все идентификаторы и их значения.
# Вывод списка всех идентификаторов # -*- coding: utf-8 -*- import tests print(dir(tests)) print(sorted(tests.__dict__.keys() )) input ()
Результат работы приложения:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'x']
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'x']
На следующем шаге мы рассмотрим инструкцию from.