Абсолютный сбой импорта в подпакете, который скрывает имя пакета stdlib

По сути, у меня есть подпакет с тем же именем, что и у стандартного пакета библиотеки («журналирование»), и я хотел бы, чтобы он мог абсолютно импортировать стандартный пакет независимо от того, как я его запускаю, но это не удается, когда я нахожусь в родительский пакет.

Это действительно похоже либо на ошибку, либо на недокументированное поведение новой поддержки «абсолютного импорта» (новое в Python 2.5). Пробовал с 2.5 и 2.6.

Макет упаковки:

foo/
    __init__.py
    logging/
        __init__.py

В foo/__init__.py мы импортируем собственный подпакет логирования:

from __future__ import absolute_import
from . import logging as rel_logging
print 'top, relative:', rel_logging

В foo/logging/__init__.py мы хотим импортировать пакет stdlib logging:

from __future__ import absolute_import
print 'sub, name:', __name__

import logging as abs_logging
print 'sub, absolute:', abs_logging

Примечание. Папка, содержащая foo, находится в sys.path.


При импорте извне/выше foo вывод будет таким, как ожидалось:

c:\> python -c "import foo"
sub, name: foo.logging
sub, absolute: <module 'logging' from 'c:\python26\lib\logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'foo\logging\__init__.pyc'>

Таким образом, абсолютный импорт в подпакете находит пакет stdlib по желанию.

Но когда мы находимся внутри папки foo, она ведет себя иначе:

c:\foo>\python25\python -c "import foo"
sub, name: foo.logging
sub, name: logging
sub, absolute: <module 'logging' from 'logging\__init__.pyc'>
sub, absolute: <module 'logging' from 'logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'c:\foo\logging\__init__.pyc'>

Двойной вывод для «sub, name» показывает, что мой собственный подпакет под названием «logging» импортирует себя во второй раз и не находит пакет «logging» stdlib, даже несмотря на то, что «absolute_import» включен .

Вариант использования заключается в том, что я хотел бы иметь возможность работать, тестировать и т. Д. Этот пакет независимо от текущего каталога. Изменение имени с «логирования» на другое было бы обходным путем, но нежелательным, и в любом случае такое поведение не соответствует описанию того, как должен работать абсолютный импорт.

Любые идеи, что происходит, является ли это ошибкой (мой или Python), или это поведение фактически подразумевается какой-то документацией?

Редактировать: ответ gahooa ясно показывает, в чем проблема. Грубый обходной путь, который доказывает, что это показано здесь:

c:\foo>python -c "import sys; del sys.path[0]; import foo"
sub, name: foo.logging
sub, absolute: <module 'logging' from 'c:\python26\lib\logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'c:\foo\logging\__init__.pyc'>

person Peter Hansen    schedule 24.12.2009    source источник


Ответы (1)


sys.path[0] по умолчанию '', что означает «текущий каталог». Поэтому, если вы находитесь в каталоге с logging, он будет выбран первым.

Я столкнулся с этим недавно, пока не понял, что на самом деле сижу в этом каталоге и что sys.path ПЕРВЫМ выбирает мой текущий каталог, прежде чем искать в стандартной библиотеке.

person gahooa    schedule 24.12.2009
comment
Спасибо. Я только что понял то же самое, когда размышлял над этим за обедом. Я предполагаю, что это неизбежно произойдет, если вы намеренно не удалите sys.path[0] или не переместите '' в конец или что-то в этом роде. Я отмечу это в своем вопросе. - person Peter Hansen; 24.12.2009