Ответ 1
Если я переместил
CreateUser.py
в основной каталог user_management, я могу легко использовать:import Modules.LDAPManager
для импортаLDAPManager.py
--- это работает.
Пожалуйста, не. Таким образом, модуль LDAPManager
, используемый CreateUser
, будет не быть таким же, как тот, который импортируется через другой импорт. Это может создать проблемы, когда у вас есть какое-то глобальное состояние в модуле или во время травления/рассыпания. Избегайте импорта, который работает только потому, что модуль находится в одном каталоге.
Если у вас есть структура пакета, вы должны:
-
Используйте относительный импорт, т.е. если
CreateUser.py
находится вScripts/
:from ..Modules import LDAPManager
Обратите внимание, что этот был (обратите внимание на прошедшее время), обескураженный PEP 8 только потому, что старые версии python не поддерживали их очень ну, но эта проблема была решена много лет назад. Текущая версия PEP 8 предлагает их в качестве приемлемой альтернативы абсолютным импортам. Я действительно люблю их внутри пакетов.
-
Используйте абсолютный импорт, используя полное имя пакета (
CreateUser.py
вScripts/
):from user_management.Modules import LDAPManager
Для того, чтобы второй работал, пакет user_management
должен быть установлен внутри PYTHONPATH
. Во время разработки вы можете настроить среду IDE, чтобы это произошло, без необходимости вручную добавлять вызовы к sys.path.append
в любом месте.
Также мне показалось странным, что Scripts/
является подпапкой. Поскольку в реальной установке модуль user_management
будет установлен под site-packages
, найденным в каталоге lib/
(какой каталог используется для установки библиотек в вашей ОС), в то время как скрипты должны быть установлены в каталоге bin/
(в зависимости от того, что содержит исполняемые файлы для вашей ОС).
На самом деле, я считаю, что Script/
не должно быть даже под user_management
. Он должен быть на уровне user_management
.
Таким образом, вам не нужно использовать -m
, но вам просто нужно убедиться, что пакет можно найти (это опять же вопрос настройки IDE, правильной установки пакета или использования PYTHONPATH=. python Scripts/CreateUser.py
для запуска скриптов с правильный путь).
Таким образом, я бы использовал следующую иерархию:
user_management (package)
|
|------- __init__.py
|
|------- Modules/
| |
| |----- __init__.py
| |----- LDAPManager.py
| |----- PasswordManager.py
|
Scripts/ (*not* a package)
|
|----- CreateUser.py
|----- FindUser.py
Тогда код CreateUser.py
и FindUser.py
должен использовать абсолютный импорт для импорта модулей:
from user_management.Modules import LDAPManager
Во время установки вы убедитесь, что user_management
заканчивается где-то в PYTHONPATH
и скриптах внутри каталога для исполняемых файлов, чтобы они могли находить модули. Во время разработки вы либо полагаетесь на конфигурацию IDE, либо запускаете CreateUser.py
добавление родительского каталога Scripts/
в PYTHONPATH
(я имею в виду каталог, который содержит как user_management
, так и Scripts
):
PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py
Или вы можете изменить PYTHONPATH
глобально, так что вам не нужно указывать это каждый раз. В ОС UNIX (Linux, Mac OS X и т.д.) Вы можете изменить один из сценариев оболочки для определения внешней переменной PYTHONPATH
, в Windows вам нужно изменить настройки переменных окружения.
Добавление Я считаю, что если вы используете python2, лучше избегать неявного относительного импорта, поставив:
from __future__ import absolute_import
в верхней части ваших модулей. Таким образом, import X
всегда означает импортировать модуль верхнего уровня X
и никогда не будет пытаться импортировать файл X.py
в том же каталоге (если этот каталог не находится в PYTHONPATH
). Таким образом, единственный способ сделать относительный импорт - использовать явный синтаксис (from . import X
), который лучше (явный лучше, чем неявный).
Это гарантирует, что вам никогда не удастся использовать "фиктивные" неявные относительные импорты, поскольку они повысят четкость ImportError
, сигнализируя, что что-то не так. В противном случае вы можете использовать модуль, который не так, как вы думаете.