Относительный импорт использует атрибут __name__ модуля для определения положения этого модуля в иерархии пакетов. Если имя модуля не содержит никакой информации о пакете (например, оно имеет значение '__main__'), то относительный импорт разрешается так, как если бы модуль был модулем верхнего уровня, независимо от того, где модуль фактически расположен в файловой системе.
В Python 2.6 добавлена возможность ссылаться на модули относительно основного модуля. PEP 366 описывает изменение.
Ответ 2
Вот решение, которое работает для меня:
Я выполняю относительный импорт как from ..sub2 import mod2 а затем, если я хочу запустить mod1.py тогда я иду в родительский каталог app и запускаю модуль, используя переключатель python -m как python -m app.sub1.mod1.
Реальная причина, по которой эта проблема возникает при относительном импорте, заключается в том, что относительный импорт работает, используя __name__ свойство модуля. Если модуль запускается напрямую, то __name__ имеет значение __main__ и не содержит никакой информации о структуре пакета. И вот почему python жалуется на relative import in non-package ошибку.
Итак, используя переключатель -m, вы предоставляете python информацию о структуре пакета, с помощью которой он может успешно разрешить относительный импорт.
Я много раз сталкивался с этой проблемой при выполнении относительного импорта. И, прочитав все предыдущие ответы, я все еще не смог понять, как решить это простым способом, без необходимости помещать шаблонный код во все файлы. (Хотя некоторые комментарии были действительно полезны, спасибо @ncoghlan и @XiongChiamiov)
Надеюсь, это поможет кому-то, кто борется с проблемой относительного импорта, потому что проходить PEP на самом деле не весело.
module_a.py выполняет import app.package_b.module_b
В качестве альтернативы 2 или 3 могли бы использовать: from app.package_a import module_a
Это будет работать до тех пор, пока у вас есть app в вашем PYTHONPATH. main.py тогда это может быть где угодно.
Итак, вы пишете setup.py для копирования (установки) всего пакета приложения и подпакетов в папки python целевой системы и main.py в папки скриптов целевой системы.
Ответ 4
"Guido рассматривает запущенные скрипты внутри пакета как антишаблон" (отклонено PEP-3122)
Я потратил так много времени, пытаясь найти решение, читая связанные сообщения здесь, о Stack Overflow, и говоря себе: "Должен быть способ получше!". Похоже, его нет.