Что на самом деле делает from __future__ import absolute_import?

| | | | | | | | |

Я ответил на вопрос об абсолютном импорте в Python, который, как мне казалось, я понял, прочитав журнал изменений Python 2.5 и сопровождающий PEP. Однако после установки Python 2.5 и попытки создать пример правильного использования из __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 Трассировка (самый последний вызов последний): Файл "pkg/main.py", строка 2 , в <модуле> print string.ascii_uppercase AttributeError: объект "module" не имеет атрибута "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 Трассировка (последний последний вызов): файл "pkg/main2.py", строка 3, < ;модуль> print string.ascii_uppercase AttributeError: объект "module" не имеет атрибута "ascii_uppercase" 

Это категорически противоречит утверждению, что import string будет всегда найдите версию std-lib с включенным абсолютным импортом. Более того, несмотря на предупреждение о том, что абсолютный импорт должен стать «новым поведением по умолчанию», я столкнулся с той же проблемой, используя оба Python 2.7, с директивой __future__ или без нее:

$ python2.7 pkg/main.py Трассировка (последний последний вызов): Файл "pkg/main.py", строка 2, в <module> print string.ascii_uppercase AttributeError: объект "module" не имеет атрибута "ascii_uppercase" $ python2.7 pkg/main2.py Трассировка (последний последний вызов): Файл "pkg/main2.py", строка 3, в <module> print string.ascii_uppercase AttributeError: объект "module" не имеет атрибута "ascii_uppercase" 

а также Python 3.5, с или без (при условии, что оператор print изменен в обоих файлах):

$ python3.5 pkg/main.py Трассировка (последний последний вызов): Файл "pkg/main.py", строка 2, в <module> print(string.ascii_uppercase) AttributeError: module "string " не имеет атрибута "ascii_uppercase" $ python3.5 pkg/main2.py Trac eback (последний последний вызов): файл "pkg/main2.py", строка 3, в <module> print(string.ascii_uppercase) AttributeError: модуль "string" не имеет атрибута "ascii_uppercase" 

Я тестировал другие варианты этого. Вместо string.py я создал пустой модуль — каталог с именем string, содержащий только пустой __init__.py — и вместо этого импорта из main.py, я использую cd"d в pkg и запускаю импорт непосредственно из REPL. Ни один из этих вариантов (ни их комбинация) изменила приведенные выше результаты. Я не могу согласовать это с тем, что я читал о директиве __future__ и абсолютном импорте.

Мне кажется, что это легко объяснимо с помощью следующего (это из документации Python 2, но это оператор остается неизменным в тех же документах для Python 3):

sys.path

(...)

Как инициализируется при запуске программы, первый элемент этого списка, path[0], — это каталог, содержащий сценарий, который использовался для вызова интерпретатора Python. y недоступен (например, если интерпретатор вызывается интерактивно или если сценарий читается из стандартного ввода), path[0] — это пустая строка, указывающая Python на поиск модулей в сначала текущий каталог.

Итак, что я упускаю? Почему оператор __future__ вроде бы не делает того, о чем говорит, и как разрешается это противоречие между этими двумя разделами документации, а также между описанным и реальным поведением?

Shop

Learn programming in R: courses

$

Best Python online courses for 2022

$

Best laptop for Fortnite

$

Best laptop for Excel

$

Best laptop for Solidworks

$

Best laptop for Roblox

$

Best computer for crypto mining

$

Best laptop for Sims 4

$

Latest questions

NUMPYNUMPY

psycopg2: insert multiple rows with one query

12 answers

NUMPYNUMPY

How to convert Nonetype to int or string?

12 answers

NUMPYNUMPY

How to specify multiple return types using type-hints

12 answers

NUMPYNUMPY

Javascript Error: IPython is not defined in JupyterLab

12 answers


Wiki

Python OpenCV | cv2.putText () method

numpy.arctan2 () in Python

Python | os.path.realpath () method

Python OpenCV | cv2.circle () method

Python OpenCV cv2.cvtColor () method

Python - Move item to the end of the list

time.perf_counter () function in Python

Check if one list is a subset of another in Python

Python os.path.join () method