Форум сайта python.su
Может ли мне кто-нибудь ответить на вопрос по относительному импорту модулей в CPython 2.6.3? Экспериментирую с from __future__ import absolute_import. Пока результат меня очень огорчает. Получается такая штука, если модуля нет в sys.path, но он не загружается (ошибка “Attempted relative import in non-package”).
Пытался сделать, как сказано тут:
http://www.python.org/dev/peps/pep-0328/#relative-imports-and-name
то есть создал набор пакетов со структурой:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
from __future__ import absolute_import
from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from .subpackage1 import moduleY
from .subpackage2.moduleZ import eggs
Traceback (most recent call last):
File "...\moduleX.py", line 3, in <module>
from .moduleY import spam
ValueError: Attempted relative import in non-package
Офлайн
KogromВ PEP есть специльное упоминание такого случая:
Если импортирую этот файл в moduleA.py, то всё работает. Но это не то, что мне нужно.
Relative Imports and __name__Другое дело что там не опиcано, что это будет ValueError(!) в случае наличия ‘.’ в пути.
Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to ‘__main__’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
Офлайн
DaevaornСпасибо.
В PEP есть специльное упоминание такого случая
DaevaornУчту.
Другое дело что там не опиcано, что это будет ValueError(!) в случае наличия ‘.’ в пути.
Офлайн
Не нужно хитрить.
Относительный импорт задуман для пакетов - не для “папок с файлами”.
Ваш package уже зарегестрирован в Питоне, надеюсь? distutils/setuptools/distribute
Тогда добавьте script для запуска - и все. Или python -m module, что не так красиво.
В конце-концов стоит подсмотреть, как делают другие…
Офлайн
Мы говорим немного на разных языках. Скорее всего от моей неосведомленности. Но есть вероятность, что это не так.
Я использую Python больше как учебный язык, так как с ним проще освоить применение юнит-тестов, да и с GUI-библиотеками (типа wxWidgets) проще знакомиться, чем, например, в C++.
Ну так вот я создал несколько модулей и к ним добавочные с юнит-тестами. При создании таких модулей удобно запускать их по одному, то есть чтобы модуль с юнит-тестом запускался как main и выполнял все свои тесты не смешиваясь с остальными.
Чтобы модули с юнит-тестами не путались с другими, я их хотел переместить в отдельную папку. Вроде всё понятно.
Андрей СветловЗачем мне мои учебные модели регистрировать? Да и вообще, мне сама эта регистрация не нравится ибо она подобна гвоздю, который прибивает мои пакеты к определенному хранилищу, что уменьшает гибкость.
Относительный импорт задуман для пакетов - не для “папок с файлами”.
Ваш package уже зарегестрирован в Питоне, надеюсь? distutils/setuptools/distribute
Андрей СветловСмотрел. Например, встроенные библиотеки, на wxPython, на IDE drpython. С первыми двумя всё понятно, а drpython хранит все свои файлы в одной папке…
В конце-концов стоит подсмотреть, как делают другие…
Офлайн
Понимаете ли, когда вы пишете import mod - этот mod должен быть как-то найден. И регистрация (установка через setup.py install/develop в простом случае) как раз это и делает.
Лучше создавать библиотеки, а не набор файлов. Это позволяет взглянуть на разработку под другим углом. И ваши вопросы отпадают.
wxPython, кстати, делает как я советую.
P.S. Для юниттестов настоятельно рекомендую http://somethingaboutorange.com/mrl/projects/nose/0.11.1/
Сможете запускать свои тесты все вместе, по одному - или в любой другой конфигурации.
Офлайн
Андрей СветловТак ведь нет проблемы найти этот mod, если он в том же пакете, что и модуль в который импортируем? Тут же не требуется регистрации. И почему я не могу указать требуемый мне модуль, как я это делаю с хедерами в C ?
Понимаете ли, когда вы пишете import mod - этот mod должен быть как-то найден. И регистрация (установка через setup.py install/develop в простом случае) как раз это и делает.
Андрей СветловЧутьё подсказывает, что это рассуждение линуксоида. Возможно, поэтому говорится так, будто контекст всем понятен, но это не так. Например, почему библиотека не может быть незарегистрированной?
Лучше создавать библиотеки, а не набор файлов. Это позволяет взглянуть на разработку под другим углом. И ваши вопросы отпадают.
Андрей СветловДля wxPython это естественно, так как его назначение оправдывает захламление PYTHONPATH и т. д.
wxPython, кстати, делает как я советую.
Андрей СветловПро nose читал (так как о нём упоминается в официальной документации). Инструментальные особенности меня мало интересуют, а вот некоторое упрощение, использование функций вместо классов - это хорошо. Но меня пока больше интересуют классические тесты, не заточенные под Python.
P.S. Для юниттестов настоятельно рекомендую http://somethingaboutorange.com/mrl/projects/nose/0.11.1/
Офлайн
1. Найти модуль получается потому, что питон неявно добавляет в sys.path папку, в которой лежит модуль __main__ (это тот .py, который вы запускаете).
Компромиссное решение, иногда приводящее к некоторым сложностям. Т.е. регистрация все же с точки зрения python engine есть.
2. В основном пишу для Windows, хотя и linux не чураюсь. Если у вас библиотека - так регистрируйте ее в Питоне. Статически через инсталляцию или динамически через модификацию sys.path. Можно еще и свой импортер написать/зарегистрировать. Импорт из файлов - это, по сути, только один из плагинов для стандартного механизма импорта. Сейчас он зашит прочно в код - но когда работа над importib закончится - будет просто одним из равноценных расширений, ничем особым не выделяющимся.
Для разработки очень полезно иметь библиотеки зарегистрированными в Питоне. А если хотите портабельность (скопировал файлы на любой комп - и они там работают) - стоит смотреть, например, в сторону py2exe. Ему даже установленный питон не нужен.
Это - правильный путь. Когда-то я начинал, думая примерно так же как и вы. Очевидно, что ваш подход кажется проще и “естественней”. Но это - ошибочное мнение.
Имел серию неприятных проблем. Причем чем проект больше - тем эти проблемы выползают все сильнее. Например, недавно мне потребовался почти год, чтобы понемногу перевести один очень большой проект в “библиотечную” форму, попутно с разработкой новых фич и фиксирования багов. Он начинался задолго до меня как относительно простая вещь. Возникали структурные сложности, которые решались созданием “костылей” - уникальных для каждого нового случая. И потом их было очень сложно удалять. Система выходит очень сложной и “хрупкой” - и с каждым новым модулем стоимость поддержки только растет.
3. Если быть точным - пишет wx.pth в site-packages. Не самое лучшее решение - но хоть что-то. Трогать PYTHONPATH вообще не рекомендую.
4. Видимо, у нас расхождения в терминологии. Для меня test предполагает *автоматический* анализ правильности его выполнения с выдачей информации об ошибках. Запустил - и увидел результат, не нажимая на кнопки. Для “скриптиков”, требующих взаимодействия в пользователем для ввода и анализа результатов есть термины example и demo.
Если же мы имеем в виду именно unittests в том смысле, который вкладывал в него Кент Бек - то должен заметить, что их структура сильно зависит от языка программирования. Так же как и шаблоны проектирования с идиомами программирования. Конечно, на Питоне можно писать так же, как и на C#. Но если делать “по питоновски” - часть идиом становится ненужными, код выходит проще, короче и понятней.
Бек создавал unittest для Явы - и там его структура понятна и оправданна. C# от Явы не сильно отличается - так что все переносится практически один-в-один.
Для C++ или Питона стоит использовать более приспособленные к особенностям языка средства.
К слову, nose является расширением unittest. Т.е. вы можете использовать его как куда более удобную “запускачку” тестов, продолжая писать их на unittest.
Отредактировано (Дек. 7, 2009 03:28:18)
Офлайн
Андрей СветловНу, в общем, про добавление в sys.path я говорил в первом сообщении.
1. Найти модуль получается потому, что питон неявно добавляет в sys.path папку, в которой лежит модуль __main__ (это тот .py, который вы запускаете).
Компромиссное решение, иногда приводящее к некоторым сложностям. Т.е. регистрация все же с точки зрения python engine есть.
Андрей СветловОк. Постараюсь проникнуться этой идеологией. py2exe смотрел, испытывал, но пока оно мне не требуется.
Для разработки очень полезно иметь библиотеки зарегистрированными в Питоне. А если хотите портабельность (скопировал файлы на любой комп - и они там работают) - стоит смотреть, например, в сторону py2exe. Ему даже установленный питон не нужен.
Андрей СветловДа, я про них и говорил. В общем, и к мысли об использовании Питона пришел после прочтения книги Кента Бека про TDD (там целая глава посвящена созданию юнит-тестов на Питоне).
Если же мы имеем в виду именно unittests в том смысле, который вкладывал в него Кент Бек - то должен заметить, что их структура сильно зависит от языка программирования.
…
Для C++ или Питона стоит использовать более приспособленные к особенностям языка средства.
Офлайн