Comments 14
Интересно, никогда не сталкивался с перекрытием имён.
0
Дальше вопрос логически следует — а как избежать перекрытия имен?
Мне кажется, решение не в том, чтоб детально разобраться, как работает импорт в 2.7 и потом следить, чтоб ненароком что-то не то не импортировать (например, выбирая безопасные названия для модулей).
Ну т.е. так вопрос решить можно, и его решают: например, если в какой-нибудь django-библиотеке foo шаблонные теги нужно загружать как
Мне кажется, что все-же лучше проблему решить тем, что всегда писать
в коде на 2.х (например, засунув эту строчку в шаблон для .py файла в IDE) и/или переходить на Python 3.x, где этот алгоритм импортирования уже по умолчанию.
Этот future-импорт убивает двух зайцев: код по семантике импортов становится как 3.х (а значит переход будет проще), и устраняется возможность сломать питоний код, просто создав рядом в папочке файл с неудачным именем. Кроме того, явное ведь лучше неявного — с absolute_imports относительные импорты нужно указывать явно.
С другими future-импортами есть проблема — их нужно писать сверху файла, и когда читаешь код, чтоб его правильно понять, нужно держать в уме, какие future-импорты действуют. С absolute_imports этой проблемы нет, т.к. во-первых, он влияет на импорты (а их тоже пишут сверху файла), а во-вторых, он меняет поведение, котрое в большинстве случаев и так было неявным или ошибочным.
Мне кажется, решение не в том, чтоб детально разобраться, как работает импорт в 2.7 и потом следить, чтоб ненароком что-то не то не импортировать (например, выбирая безопасные названия для модулей).
Ну т.е. так вопрос решить можно, и его решают: например, если в какой-нибудь django-библиотеке foo шаблонные теги нужно загружать как
{% load "foo_tags" %}
, то вероятность 92.64%, что боролись с семантикой импортов (либо это cargo-cult, оставшийся от какой-то библиотеки, боровшейся с семантикой импортов). Мне кажется, что все-же лучше проблему решить тем, что всегда писать
from __future__ import absolute_imports
в коде на 2.х (например, засунув эту строчку в шаблон для .py файла в IDE) и/или переходить на Python 3.x, где этот алгоритм импортирования уже по умолчанию.
Этот future-импорт убивает двух зайцев: код по семантике импортов становится как 3.х (а значит переход будет проще), и устраняется возможность сломать питоний код, просто создав рядом в папочке файл с неудачным именем. Кроме того, явное ведь лучше неявного — с absolute_imports относительные импорты нужно указывать явно.
С другими future-импортами есть проблема — их нужно писать сверху файла, и когда читаешь код, чтоб его правильно понять, нужно держать в уме, какие future-импорты действуют. С absolute_imports этой проблемы нет, т.к. во-первых, он влияет на импорты (а их тоже пишут сверху файла), а во-вторых, он меняет поведение, котрое в большинстве случаев и так было неявным или ошибочным.
+2
Спасибо огромное за комментарий. Он помог обнаружить, что часть статьи оказалась неопубликованной в результате ошибки во время форматирования. А именно вот это:
В случае возникновения подобных коллизий имен возможны следующие решения:
- Переименовать модуль, либо пакет таким образом, чтобы имя пакета не совпадало с именем модуля, т.е. исключить совпадение имен
- Иногда может помочь включение абсолютных путей по умолчанию для импорта с помощью инструкции from __future__ import absolute_import (на самом деле в этом случае, лишь повышается контроль за последовательностью поиска пакетов и модулей путем внесения изменений в sys.path)
0
Еще добавлю про импорты.
Неоднозначное поведение когда вызывается код из модуля из пэкэджа, в котором вызывается сабпэкэдж с модулями.
Как оказалось функция __import__ не выполняет магию и путь не добавляется в paths. Долго промучался, потом увидел, что во всех сабмодулях импорт идет напрямую и работает, заменил на путь от корня программы (был например пэкэдж admin внутри модуль show внутри этого модуля, для загрузки admin.submodules надо было писать именно так, а не как ожидаемо (просто submodules)).
Структура
Неоднозначное поведение когда вызывается код из модуля из пэкэджа, в котором вызывается сабпэкэдж с модулями.
Как оказалось функция __import__ не выполняет магию и путь не добавляется в paths. Долго промучался, потом увидел, что во всех сабмодулях импорт идет напрямую и работает, заменил на путь от корня программы (был например пэкэдж admin внутри модуль show внутри этого модуля, для загрузки admin.submodules надо было писать именно так, а не как ожидаемо (просто submodules)).
Структура
plugins.py - файл_с__import__
admin/__init__.py - ясно
admin/show.py - файл с импортом плагинов
admin/submodules/__init__.py - пэкэдж
admin/submodules/billing.py - файл что надо импортнуть
+1
Выходило примерно так
plugins.py
admin/show.py
Результат был что-то вроде ImportError No module named billing
plugins.py
for i in ['admin.show','test.test']:
__import__(i)
admin/show.py
import submodules
for i in submodules.__all__:
__import__('submodules.'+i)
Результат был что-то вроде ImportError No module named billing
0
Не мучайте __import__, используйте docs.python.org/2/library/importlib.html
Вопросов станет поменьше
Вопросов станет поменьше
0
Importlib тоже подвержен этой проблеме.
0
Параметр package вниманием не обошли?
0
И так и так пробовал, нужно прописывать точно путь, тогда работает.
0
>>> import ctypes
>>> ctypes.__package__
'ctypes'
>>> import importlib
>>> m = importlib.import_module('util', package=ctypes.__package__)
Traceback (most recent call last):
File "", line 1, in File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
ImportError: No module named util
>>> m = importlib.import_module('.util', package=ctypes.__package__)
>>> m.__name__
'ctypes.util'
>>>
>>> ctypes.__package__
'ctypes'
>>> import importlib
>>> m = importlib.import_module('util', package=ctypes.__package__)
Traceback (most recent call last):
File "", line 1, in File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
ImportError: No module named util
>>> m = importlib.import_module('.util', package=ctypes.__package__)
>>> m.__name__
'ctypes.util'
>>>
0
Отличная статья, но для полноты было бы неплохо добавить про PYTHONHOME, PYTHONPATH и модули в зипах.
+2
Для полноты картины многое можно добавить:
asvetlov.blogspot.com/2010/05/blog-post.html
asvetlov.blogspot.com/2010/05/2.html
asvetlov.blogspot.com/2010/05/3.html
asvetlov.blogspot.com/2010/05/blog-post.html
asvetlov.blogspot.com/2010/05/2.html
asvetlov.blogspot.com/2010/05/3.html
+1
Sign up to leave a comment.
О порядке поиска пакетов и модулей для импорта в Python