У меня есть структура проекта с голыми костями с в основном пустыми файлами python для тестирования концепции из онлайн-учебника:
project
|--package1
| |--__init__.py
| |--module1.py
|
|--package2
| |--__init__.py
| |--module2.py
|
|--__init__.py
модуль1.py:
from .package2.module2 import function2
модуль2.py:
def function2():
return 0
Запуск module1.py напрямую приводит к этой ошибке:
Traceback (most recent call last):
File "c:\"blahblahblah"\project\package1\module1.py", line 1, in <module>
from .package2.module2 import function2
ImportError: attempted relative import with no known parent package
Я попытался уменьшить сложность проблемы, поместив module2.py в саму папку проекта и изменив импорт, как предполагает мой учебник (из .module2 import function2), но это дает ту же ошибку.
примечание: у меня сложилось впечатление, что файлы инициализации не нужны для моей версии Python, но я добавил их, чтобы охватить все мои базы.
Python версии 3.9.1
Любые подсказки будут высоко оценены.






Вы можете присоединиться к пути внешнего пакета внутри пути вашего источника для импорта относительного модуля:
import os, sys
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
Я думаю, после этого вы можете напрямую сделать:
from package2.module2 import function2
Когда вы выполняете сценарий Python, конкретный каталог, в котором находится сценарий, добавляется к пути, но не его родительский каталог.
Вам нужно будет добавить корневой каталог к пути, чтобы Python мог найти package2.
Для этого вы можете использовать модуль pathlib (Python 3.4 или выше), изменив module1.py таким образом:
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from package2.module2 import function2
Метод Path.resolve() возвращает абсолютный путь к файлу, а с помощью parent.parent вы получаете родительский каталог module1.py (корневой каталог). Поэтому Python теперь сможет найти package2.
Кроме того, поскольку вы получаете абсолютный путь, импорт будет работать независимо от того, выполняется ли скрипт из каталога project или из package1.
Вы все равно получите ImportError: attempted relative import with no known parent package, потому что при выполнении module1.py атрибут __package__ будет None.
Это объясняется в PEP 336. Обратите внимание на часть, в которой говорится: «Чтобы разрешить относительный импорт, когда модуль выполняется напрямую, перед первым оператором относительного импорта потребуется шаблон, подобный следующему [...] Обратите внимание, что этого шаблона достаточно, только если пакет верхнего уровня уже доступен через sys.path. Для работы прямого выполнения потребуется дополнительный код, управляющий sys.path [...]».
Спасибо @Диего! Это дает мне более фундаментальное понимание того, что здесь происходит.
Относительный импорт не сработал, потому что module1.py не мог заглянуть в свою родительскую папку для получения дополнительных пакетов при прямом выполнении.
Для правильного вызова требовался параметр -m для обозначения того, что module1 был модулем внутри пакета. Моему терминалу также нужно было перейти на один каталог вверх:
PS C:\...\"parent of project folder"> python -m project.package1.module1
Также необходимо изменить module1.py:
from ..package2.module2 import function2
Это немного более подробно, чем я надеялся, что это будет. Я читал эту статью/учебник по относительному импорту: realpython.com/absolute-vs-relative-python-imports Эта статья показала, что это можно сделать без указания путей. Как вы думаете, возможна ли такая авторская стратегия?