Начать, видимо, следует с того, что речь пойдет об интерпретаторе CPython версии 2.7.x (примеры тестировались на версии 2.7.3).
Официальный сайт содержит описания оператора импорта и модулей на Python:
Из этого следует, что в Python существуют пакеты (package), модули (module) и имена, определенные в модулях (names).Также следует отметить, что в некоторых частях документации модули называются подмодулями, если они помещены внутри пакета.
В Python оператор импорта позволяет импортировать пакеты, модули и имена в пространство имен, в котором выполняется оператор импорта.
Есть две интересные особенности:
- Синтаксис оператора импорта не всегда дает понять, что именно следует импортировать: пакет, модуль или имя.
- Синтаксис оператора импорта не может явно указать, что путь к модулю является абсолютным путем (хотя можно явно указать, что путь является относительным, а также можно изменить семантику оператора с точки зрения использования абсолютный путь по умолчанию, см.
- Импортировать ПАКЕТ abcd или импортировать МОДУЛЬ abcd.
- Импортировать пакет/модуль abcd из ТЕКУЩЕГО ПАКЕТА (из пакета модуля, в котором выполняется импорт abcd), либо ИЗ ПАКЕТА в соответствии со списком каталогов, указанным в sys.path
- from abcd import defg: (импортировать модуль defg из пакета abcd, или импортировать пакет defg из пакета abcd, или импортировать имя defg из пакета abcd, или импортировать имя defg из модуля abcd) X (из того же пакета или из пакета в соответствии с sys .
путь)
- import abcd.defg: (импортировать пакет defg из пакета abcd, импортировать модуль defg из пакета abcd) X (из того же пакета или из пакета согласно sys.path)
Этот алгоритм в той или иной форме описан в официальной документации Python. Алгоритм поиска имени для импорта abcd Поиск имени abcd для импорта происходит по следующему алгоритму:
№ | Что мы ищем? | Куда мы смотрим* | Комментарий |
---|---|---|---|
1 | пакет abcd | в пакете текущего модуля (модуля, в котором выполняется импорт abcd) | только если текущий модуль сам содержится в пакете** |
2 | модуль abcd | в пакете текущего модуля (модуля, в котором выполняется импорт abcd) | только если текущий модуль сам содержится в пакете** |
3 | модуль abcd | во встроенных модулях | Ссылка на документацию представлена в *** |
4 | пакет abcd | в каталогах, указанных в sys.path | ссылка на документацию указана в **** |
5 | модуль abcd | в каталогах, указанных в sys.path | ссылка на документацию указана в **** |
* Информация о приоритете поиска пакета над модулем установлена опытным путем; в документации это явно не указано.
** В данном случае переменная __package__ этого модуля равна имени пакета, в противном случае — None. Ссылка на документацию: docs.python.org/2/tutorial/modules.html#intra-package-references «На самом деле, такие ссылки настолько распространены, что оператор импорта сначала просматривает содержащий его пакет, а затем ищет стандартный путь поиска модуля».
(!!!) Здесь стоит отметить, что нигде в этом же документе об этом факте нет упоминания( http://docs.python.org/2/tutorial/modules.html#the-module-search-path ), что вводит в заблуждение (см.
(!!!) Второе, что следует отметить, этот шаг поиска присутствует только в том случае, если модуль, в котором выполняется import abcd, сам импортирован из пакета (т.е.
с помощью команды import .
).
Если этот модуль импортируется без указания пакета или модуль выполняется как скрипт, этот шаг будет пропущен.
Это отражено в документе www.python.org/dev/peps/pep-0302/#id23 : «Встроенная функция __import__ (известная как PyImport_ImportModuleEx() в import.c) затем проверит, является ли модуль, выполняющий импорт, пакетом или подмодулем пакета.
Если это действительно пакет (подмодуль a), он сначала пытается выполнить импорт относительно пакета (родительского пакета для подмодуля).
Например, если пакет с именем «спам» «импортирует яйца», он сначала будет искать модуль с именем «spam.eggs».
Если это не удается, импорт продолжается как абсолютный импорт: он будет искать модуль с именем «eggs».
*** docs.python.org/2/tutorial/modules.html#the-module-search-path «Когда импортируется модуль с именем спам, интерпретатор сначала ищет встроенный модуль с таким именем».
**** docs.python.org/2/tutorial/modules.html#the-module-search-path «Если он не найден, он ищет файл с именем spam.py в списке каталогов, заданном переменной sys.path».
Алгоритм поиска имени для импорта abcd.defg Сначала пакет или модуль abcd ищется по алгоритму, описанному для импорта abcd. Если поиск успешен, пакет или модуль defg ищется по следующему алгоритму:
№ | Что мы ищем? | Куда мы смотрим* | Комментарий |
---|---|---|---|
1 | пакет defg | в упаковке abcd | ссылка на документацию указана в ** |
2 | модуль defg | в упаковке abcd | ссылка на документацию указана в ** |
** www.python.org/dev/peps/pep-0302/#id23 «Глубже в механизме импорт точечных имен разделяется по компонентам.
Для «import spam.ham» сначала выполняется «импорт спама», и только когда это удается, «ham» импортируется как подмодуль «spam».
Алгоритм поиска имени для файла abcd.defg import ghi Сначала пакет или модуль abcd.defg ищется по алгоритму, описанному для импорта abcd.defg:
№ | Что мы ищем? | Куда мы смотрим? |
---|---|---|
1 | имя Ги | в пакете или модуле defg |
2 | пакет Ги | в пакете defg |
3 | модуль ги | в пакете defg |
Представьте себе следующую ситуацию: есть модуль abcd и пакет abcd, который, в свою очередь, содержит модуль defg, модуль abcd и пакет abcd расположены в разных каталогах, а модуль abcd находится в том же пакете, что и модуль, в котором находится Выполняется оператор import abcd.defg. В этом случае импорт завершится с ошибкой.
Это связано с тем, что интерпретатор Python сначала найдет модуль abcd, а затем попытается найти в нем модуль defg, что невозможно.
Было бы разумнее определить из синтаксиса оператора импорта, что abcd может быть только пакетом (поскольку все элементы до этого момента могут быть только пакетами) и искать abcd только как пакет. В этом случае пакет abcd будет импортирован из другого каталога, в нем будет обнаружен модуль defg и выполнение программы продолжится без ошибок.
К сожалению, такое поведение не реализовано в Python. См.
bugs.python.org/issue16891#msg179353 .
Автор статьи столкнулся с этой проблемой, но из-за несоответствия описания в официальной документации Python потребовалось некоторое время, чтобы выяснить причины такого поведения интерпретатора.
В результате возникли следующие дискуссии.
stackoverflow.com/questions/14183541/why-python-finds-module-instead-of-package-if-they-have-the-same-name И bugs.python.org/issue16891 , и эта статья тоже была написана.
В случае таких конфликтов имен возможны следующие решения:
- Переименуйте модуль или пакет так, чтобы имя пакета не совпадало с именем модуля, т.е.
исключите совпадения имен.
- Иногда может помочь включение абсолютных путей по умолчанию для импорта с помощью оператора from __future__ import Absolute_import (фактически в этом случае он лишь увеличивает контроль над последовательностью поиска пакетов и модулей за счет внесения изменений в sys.path)
Теги: #python #импорт #python
-
Отношения Между Таблицами Базы Данных
19 Oct, 24 -
Драйвер Sql Server 2005 Для Php
19 Oct, 24 -
О Законе Парето И Выводах Из Него
19 Oct, 24 -
Факс Для Webplanet
19 Oct, 24