Я ответил на вопрос об абсолютном импорте в Python, который, как мне показалось, я понял, прочитав журнал изменений Python 2.5 и сопровождающий его PEP . Однако после установки Python 2.5 и попытки создать пример правильного использования from __future__ import absolute_importя понимаю, что все не так ясно.
Прямо из журнала изменений, указанного выше, это утверждение точно подытожило мое понимание абсолютного изменения импорта:
Допустим, у вас есть каталог пакетов, подобный этому:
pkg/ pkg/__init__.py pkg/main.py pkg/string.pyЭто определяет пакет с именем ,
pkgсодержащейpkg.mainиpkg.stringподмодули.Рассмотрим код в модуле main.py. Что произойдет, если он выполнит оператор
import string? В Python 2.4 и более ранних версиях он сначала просматривает каталог пакета для выполнения относительного импорта, находит pkg / string.py, импортирует содержимое этого файла какpkg.stringмодуль, и этот модуль привязывается к имени"string"вpkg.mainпространстве имен модуля.
Итак, я создал эту точную структуру каталогов
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.pyи string.pyпусты. main.pyсодержит следующий код:
import string
print string.ascii_uppercase
Как и ожидалось, запуск этого с Python 2.5 завершится неудачно с AttributeError:
$ python2.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Однако далее в журнале изменений 2.5 мы находим это (выделение добавлено):
В Python 2.5 вы можете переключать
importповедение на абсолютный импорт, используяfrom __future__ import absolute_importдирективу. Такое поведение абсолютного импорта станет будущим по умолчанию в будущей версии (возможно, Python 2.7). Как только абсолютный импорт по умолчанию,import stringвсегда найдет версию стандартной библиотеки.
Таким образом, я создал pkg/main2.py, идентичный, main.pyно с дополнительной директивой импорта в будущем. Теперь это выглядит так:
from __future__ import absolute_import
import string
print string.ascii_uppercase
Запуск этого с Python 2.5, однако ... не удается с AttributeError:
$ python2.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Это довольно категорически противоречит тому , что import stringбудет всегда найти версию станд-LIB с поддержкой абсолютного импорта. Более того, несмотря на предупреждение о том, что абсолютный импорт должен стать «новым режимом по умолчанию», я столкнулся с той же проблемой, используя оба языка Python 2.7, с __future__директивой или без нее:
$ python2.7 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2.7 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
а также Python 3.5, с или без (при условии, что printоператор изменяется в обоих файлах):
$ python3.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
$ python3.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
Я проверил другие варианты этого. Вместо этого string.pyя создал пустой модуль - каталог с именем, stringсодержащим только пустой __init__.py- и вместо того, чтобы выдавать импорт из main.py, я должен cdбыл pkgвыполнять импорт непосредственно из REPL. Ни один из этих вариантов (ни их комбинация) не изменил результаты выше. Я не могу совместить это с тем, что я прочитал о __future__директиве и абсолютном импорте.
Мне кажется, что это легко объяснить следующим (это из документов Python 2, но это утверждение остается неизменным в тех же документах для Python 3):
sys.path
(...)
Как инициализируется при запуске программы, первым элементом этого списка
path[0]является каталог, содержащий скрипт, который использовался для вызова интерпретатора Python. Если каталог скриптов недоступен (например, если интерпретатор вызывается в интерактивном режиме или если скрипт читается из стандартного ввода),path[0]это пустая строка, которая направляет Python для поиска модулей в текущем каталоге в первую очередь.
Так чего мне не хватает? Почему __future__утверждение, по-видимому, не соответствует тому, что оно говорит, и каково разрешение этого противоречия между этими двумя разделами документации, а также между описанным и фактическим поведением?