Импорт Python - почему требуется имя основного пакета? - PullRequest
0 голосов
/ 23 сентября 2019

Я хотел бы знать, почему мне нужно включить имя основного каталога в операторы import для создания структуры каталогов моего проекта.

Структура моего проекта

.
├── main.py
├── myModel
│   ├── __init__.py
│   ├── loader
│   │   ├── __init__.py
│   │   └── dataset_loader.py
│   └── models
│       ├── __init__.py
│       ├── static_model.py
│       └── task_model.py
└── tree.txt

main.py

from myModel import loader
from myModel import models

loader.fun ()
loader.dataset_loader.fun ()

myModel / __ init __. py

import myModel.models
import myModel.loader

myModel / loader / __ init __. py

from myModel.loader.dataset_loader import *

myModel / models / __ init __. py

from myModel.models.static_model import StaticModel

Мой первый вопрос: почему мне нужно поместить myModel даже в подпапки каталога myModel.Я попытался удалить его, но import не сработал, поэтому я думаю, что он должен быть там.

Во-вторых, почему я могу позвонить fun напрямую из loader и не использовать полный путь?

Я читаю что-то в Интернете .Но мне все еще трудно понять, почему это происходит.

1 Ответ

2 голосов
/ 23 сентября 2019

Абсолютный импорт, например import x.y.z или from x.y import z, требует x, чтобы быть на вашем пути.В вашем конкретном случае myModel находится на пути из-за вашего рабочего каталога.Подпакеты не находятся на пути, и поэтому могут быть доступны только путем повторения корневого пакета.

Более интуитивным подходом может быть использование относительных путей.Это возможно, потому что все ваши файлы живут в правильных пакетах с __init__ файлами.Имейте в виду, что относительные пути подразумевают, что у вас есть модули, которые предназначены для использования в структуре вашего пакета, а не сами по себе.В противном случае вы можете столкнуться с ошибками при попытке запуска некоторых модулей в виде автономных сценариев.

Измените myModel/__init__.py на:

from . import models
from . import loader

. делает импорт относительным,Обратите внимание, что я не предлагал изменять main.py, поскольку он находится за пределами ваших пакетов.Добавление дополнительных точек позволяет повысить уровень иерархии файлов.

Измените myModel/loader/__init__.py на

from .dataset_loader import *

и myModel/models/__init__.py на

from .static_model import StaticModel

An import оператор связывает имя в вашем локальном пространстве имен (обычно это модуль, в котором вы его выполняете).Имя, которое будет связано, зависит от того, какую форму import вы использовали:

  1. import x связывает модуль, описанный в x.py или x/__init__.py, с именем x
  2. import x.y связывает модуль, описанный в x.py или x/__init__.py, с именем x и гарантирует, что x имеет атрибут y, либо как атрибут, определенный в x.py / __init__.pyили как субмодуль в x/y.py.
  3. from x import y связывает атрибут или субмодуль y из x.py / x/__init__.py или x/y.py с именем y.Эта опция загружается, но не дает вам доступа к x.

Когда вы запускаете from myModel import loader, вы получаете объект модуля loader, который имеет атрибут callable fun.

...