относительный импорт на CDSW
У меня есть проект на CDSW, организованный следующим образом:
/home/cdsw/my_project_v2.1
|_>input
|_>output
|_>scr
|_>__init__.py
|_>main.py
|_>utils
|_>__init__.py
|_>helpers.py
в моем текущем коде я использую sys.path.append
для выполнения моего импорта.
import sys
sys.path.append("/home/cdsw/my_project_v2.1/src/utils/")
from helpers import bar
Это работает нормально, но это плохая практика, потому что если версия изменится, мне нужно будет изменить все мои сценарии, которые используют путь.
Я хотел заменить его относительным путем:
from .utils.helpers import bar
Но я получил ошибку:
$ pwd
/home/cdsw
$ python3 my_project_v2.1/src/main.py
Traceback (most recent call last):
File "my_project_v2.1/src/main.py", line 1, in <module>
from .utils.helpers import bar
ModuleNotFoundError: No module named '__main__.helpers'; '__main__' is not a package
что мне нужно изменить в моей архитектуре или в моем коде, чтобы он заработал?
1 ответ
Просто используйте
from utils.helpers import bar
Краткая выдержка из документации аргументов командной строки Python:
Если имя сценария относится непосредственно к файлу Python, каталог, содержащий этот файл, добавляется в начало
sys.path
, и файл выполняется как__main__
модуль.
Первая половина предложения означает, что вы можете использовать абсолютные имена модулей при обращении к содержимому вашего каталога, потому что Python будет искать модуль там. Тот факт, что вы не можете использовать относительный импорт, является следствием второй половины предложения.
В качестве примечания, вы также можете рассмотреть возможность исключения номера версии из имени каталога или, что еще лучше, поместить свой код прямо в /home/cdsw
. Последнее может показаться странным, поскольку вы никогда не сделаете этого на обычной машине, но здесь все находится в контейнере, и на самом деле именно так ваш код должен быть организован в CDSW. Вы можете подтвердить это, создав новый проект на основе шаблона или URL-адреса git - оба кода поместят код непосредственно в домашний каталог.