dir0dir1dir2mod.py
и инструкции импортирования, имеющей следующий вид:
import dir1.dir2.mod
применяются следующие правила:
• dir1 и dir2 должны содержать файл __init__.py.
• dir0, каталог-контейнер, может не содержать файл __init__.py – этот файл
будет проигнорирован, если он присутствует.
• dir0, но не dir0dir1, должен присутствовать в пути поиска модулей (то есть он должен быть домашним каталогом или присутствовать в переменной окружения PYTHONPATH и так далее).
Таким образом, структура каталогов в этом примере должна иметь следующий вид (здесь отступы указывают на вложенность каталогов):
dir0 # Каталог-контейнер в пути поиска модулей
dir1
__init__.py
dir2
__init__.py
mod.py
Файлы __init__.py могут содержать программный код на языке Python, как любые другие файлы модулей. Отчасти они являются объявлениями для интерпретатора и могут вообще ничего не содержать. Эти файлы, будучи объявлениями, предотвращают неумышленное сокрытие в каталогах с совпадающими именами истинно требуемых модулей, если они отображаются позже в списке путей поиска модулей. Без этого защитного механизма интерпретатор мог бы выбирать каталоги, которые не имеют никакого отношения к вашему программному коду, только лишь потому, что в пути поиска они появляются ранее.
В общем случае файл __init__.py предназначен для выполнения действий по инициализации пакета, создания пространства имен для каталога и реализации поведения инструкций from * (то есть from … import *), когда они используются для импортирования каталогов:
Инициализация пакета
Когда интерпретатор Python импортрирует каталог в первый раз он автоматически запускает программный код файла __init__.py этого каталога. По этой причине обычно в эти файлы помещается программный код, выполняющий действия по инициализации, необходимые для файлов в пакете.
Например, этот файл инициализации в пакете может использоваться для создания файлов с данными, открытия соединения с базой данных и так далее. Обычно файлы __init__.py не предназначены для непосредственного выполнения – они запускаются автоматически, когда выполняется первое обращение к пакету.
Инициализация пространства имен модуля
При импортировании пакетов пути к каталогам в вашем сценарии после завершения операции импортирования превращаются в настоящие иерархии вложенных объектов. Например, в предыдущем примере после завершения операции импортирования можно будет использовать выражение dir1.dir2, которое возвращает объект модуля, чье пространство имен содержит все имена, определяемые файлом __init__.py из каталога dir2. Такие файлы создают пространства имен для объектов модулей, соответствующих каталогам, в которых отсутствуют настоящие файлы модулей.
Поведение инструкции from *
В качестве дополнительной особенности, в файлах __init__.py можно использовать списки __all__, чтобы определить, что будет импортироваться из каталог
Основы операции импортирования пакетов
import dir1.dir2.mod
from dir1.dir2.mod import x
Автор: Няшный Человек
Дата публикации: 2015-12-15T22:28:00.000+02:00
Основы использования функции reload
• reload – это не инструкция, а функция.
• Функции reload передается существующий объект модуля, а не имя.
• В Python 3.0 функции reload находится в модуле imp, который требуется импортировать, чтобы получить доступ к функции. Функция reload ожидает получить объект, поэтому к моменту ее вызова модуль уже должен быть успешно импортирован (если операция импорта оказалась неудачной из-за синтаксических или каких-либо других ошибок, вам может потребоваться повторить ее, прежде чем можно будет повторно загрузить модуль).
Кроме того, синтаксис инструкции import и функции reload отличается: аргумент должен передаваться функции reload в круглых скобках, а инструкции import – без них. Повторная загрузка модуля выполняется примерно следующим образом:
import module # Первоначальное импортирование
…используются атрибуты модуля…
… # Теперь выполняются изменения в файле модуля
…
from imp import reload # Импортировать функцию reload (в 3.0)
reload(module) # Загрузить обновленный модуль
…используются атрибуты модуля…
Это типичный случай, когда вы импортируете модуль, затем изменяете исходный программный код в текстовом редакторе, а потом повторно загружаете его. Когда вы вызываете функцию reload, интерпретатор повторно читает файл с исходными текстами и выполняет инструкции, находящиеся на верхнем уровне. Пожалуй, самое важное, что следует знать о функции reload, – это то, что она изменяет непосредственно сам объект модуля – она не удаляет и не создает его повторно. Вследствие этого все ссылки на объект модуля, имеющиеся в программе, автоматически будут учитывать изменения, произошедшие в результате повторной загрузки. А теперь подробнее о том, как происходит повторная загрузка:
• Функция reload запускает новый программный код в файле модуля в текущем пространстве имен модуля. При повторном выполнении программный код перезаписывает существующее пространство имен вместо того, чтобы удалять его и создавать вновь.
• Инструкции присваивания на верхнем уровне файла замещают имена новыми значениями. Например, повторный запуск инструкции def приводит к замещению предыдущей версии функции в пространстве имен модуля, выполняя повторную операцию присваивания имени функции.
• Повторная загрузка оказывает воздействие на всех клиентов, использовавших инструкцию import для получения доступа к модулю. Клиенты, использовавшие инструкцию import, получают доступ к атрибутам модуля, указывая полные их имена, поэтому после повторной загрузки они будут получать новые значения атрибутов.
• Повторная загрузка будет воздействовать лишь на тех клиентов, которые еще только будут использовать инструкцию from в будущем. Клиенты, которые использовали инструкцию from для получения доступа к атрибутам в прошлом, не заметят изменений, произошедших в результате повторной загрузки, – они по-прежнему будут ссылаться на старые объекты, полученные до выполнения перезагрузки.
Автор: Няшный Человек
Дата публикации: 2015-11-21T16:54:00.000+02:00
Повторная загрузка модулей
• При вызове операции импортирования (с помощью инструкций import и from) программный код модуля загружается и выполняется, только когда модуль импортируется в первый раз за время работы программы.
• При последующих попытках импортировать модуль будет использоваться объект уже загруженного модуля. Повторная загрузка и запуск программного кода в этом случае не происходит.
• Функция reload принудительно выполняет повторную загрузку уже загруженного модуля и запускает его программный код. Инструкции присваивания, выполняемые при повторном запуске, будут изменять существующий объект модуля.
Для чего вся эта суета вокруг повторной загрузки модулей? Функция reload позволяет изменять части программы, не останавливая всю программу. Благодаря функции reload эффект от изменений в программном коде можно наблюдать сразу же после внесения этих изменений. Повторная загрузка модулей поможет не во всех ситуациях, но она позволит существенно сократить цикл разработки. Например, представьте себе программу, предназначенную для работы с базами данных, которая должна при запуске соединиться с сервером, – так как изменения или настройки могут проверяться немедленно после повторной
загрузки, вам достаточно соединиться с базой данных всего один раз за весь сеанс отладки. Таким же способом можно обновлять программный код долго работающих серверов, которые нельзя останавливать.
Язык Python относится к языкам интерпретирующего типа (более или менее), поэтому в нем отсутствуют этапы компиляции/компоновки, необходимые, чтобы запустить программу, например, на языке C модули загружаются динамически уже запущенной программой. Возможность повторной загрузки обеспечивает повышение производительности труда, позволяя вам изменять части работающей программы без ее остановки. Обратите внимание, что в настоящее время функция reload может обслуживать только модули, написанные на языке Python, – скомпилированные модули расширений, написанные на таких языках, как C, тоже могут динамически загружаться во время работы программы, но их нельзя загрузить повторно.
Автор: Няшный Человек
Дата публикации: 2015-11-15T12:57:00.000+02:00
Вложенные пространства имен
Файл mod3.py определяет единственное глобальное имя и атрибут операцией присваивания:
X = 3
Файл mod2.py определяет свою переменную X, затем импортирует модуль mod3 и спользует квалификацию имени, чтобы получить доступ к атрибуту импортированного модуля:
X = 2
import mod3
print(X, end=’ ‘) # Моя глобальная переменная X
print mod3.X # Глобальная переменная X из модуля mod3
Файл mod1.py также определяет свою собственную переменную X, затем импортирует модуль mod2 и получает значения атрибутов обоих модулей:
X = 1
import mod2
print(X, end=’ ‘) # Моя глобальная переменная X
print(mod2.X, end=’ ‘) # Переменная X из модуля mod2
print(mod2.mod3.X # Переменная X из модуля mod3
В действительности, когда mod1 импортирует mod2, он создает двухуровневое вложение пространств имен. Используя полный путь к имени mod2.mod3.X, он может погрузиться в модуль mod3, который вложен в импортированный модуль mod2. Суть в том, что модуль mod1 может обращаться к переменным X во всех трех файлах и, следовательно, имеет доступ ко всем трем глобальным областям видимости:
% python mod1.py
2 3
1 2 3
Однако обратное утверждение неверно: модуль mod3 не имеет доступа к именам в mod2, а модуль mod2 не имеет доступа к именам в mod1. Возможно, этот пример будет проще понять, если отвлечься от пространств имен и областей видимости и сосредоточиться на объектах, задействованных в примере. mod2 внутри модуля mod1 – это всего лишь имя, которое ссылается на объект с атрибутами, некоторые из которых могут ссылаться на другие объекты с атрибутами (инструкция import выполняет операцию присваивания). Для таких путей, как
mod2.mod3.X, интерпретатор Python выполняет вычисления слева направо, извлекая атрибуты из объектов.
Обратите внимание: в mod1 можно вставить инструкцию import mod2 и затем использовать обращение mod2.mod3.X, но нельзя записать import mod2.mod3 – такой синтаксис используется для операции импортирования пакетов (каталогов), которая будет описана в следующей главе. При импортировании пакетов также создаются вложенные пространства имен, но в этом случае инструкция import воспринимает свой аргумент как дерево каталогов, а не как цепочку модулей.
Автор: Няшный Человек
Дата публикации: 2015-11-11T22:57:00.000+02:00
Импортирование и области видимости
Например, рассмотрим два следующих простых модуля. Первый, в файле moda.py,
определяет переменную X, которая является глобальной только для программного кода в этом файле, и функцию, изменяющую глобальную переменную X
в этом файле:
X = 88 # Переменная X: глобальная только для этого файла
def f():
global X # Изменяет переменную X в этом файле
X = 99 # Имена в других модулях недоступны
Второй модуль, modb.py, определяет свою собственную глобальную перемен-
ную X, а также импортирует и вызывает функцию из первого модуля:
X = 11 # Переменная X: глобальная только для этого файла
import moda # Получает доступ к именам в модуле moda
moda.f() # Изменяет переменную moda.X, но не X в этом файле
print X, moda.X
При запуске этого модуля функция moda.f изменит переменную X в модуле moda, а не в modb. Глобальной областью видимости для функции moda.f всегда является файл, вмещающий ее, независимо от того, из какого модуля она была вызвана:
% python modb.py
11 99
Другими словами, операция импортирования никогда не изменяет область видимости для программного кода в импортируемом файле – из импортируемого файла нельзя получить доступ к именам в импортирующем файле. Если быть более точным:
- Функциям никогда не будут доступны имена, определенные в других функциях, если только они физически не вложены друг в друга.
- Программному коду модуля никогда не будут доступны имена, определенные в других модулях, если только они явно не были импортированы.
Это поведение является частью понятия лексической области видимости –
в языке Python области видимости, доступные части программного кода полностью определяются физическим расположением этого программного кода
в файле. Области видимости не подвержены влияниям вызовов функций или
операции импортирования.
Автор: Няшный Человек
Дата публикации: 2015-10-04T08:43:00.000+03:00