Пути импорта – правильный путь?

Я знаю, что есть много похожих или одинаковых вопросов, но я все еще не могу понять / найти правильный способ для работы с модулями. Python – мой любимый язык, и мне нравится все в нем, кроме работы с импортом: рекурсивный импорт (когда вы пытаетесь ссылаться на имя, которое еще не существует), пути импорта и т. Д.

Итак, у меня есть такая структура проекта:

my_project/ package1/ __init__.py module1 module2 package2/ __init__.py module1 module2 

Package1 может использоваться автономным блоком, но также ожидается, что он будет импортирован package2 . Что я сейчас делаю, это то, что, например, в package1.module1 я пишу from package1 import module2 , то есть используя полный путь к импортированному модулю. Я делаю это, потому что если я использую import module2 – это не будет работать, когда модуль будет импортирован из другого пакета ( package2 ). Я также не могу использовать from . import module2 from . import module2 – это не будет работать при непосредственном запуске module1 .

ОК, так что from package1 import module2 в package1.module1 работать в обоих случаях (при запуске непосредственно package1.module1 и при импорте из package2 ) я добавляю эти строки в начало package1.module1 :

 import os, sys currDir = os.path.dirname(os.path.realpath(__file__)) rootDir = os.path.abspath(os.path.join(currDir, '..')) if rootDir not in sys.path: # add parent dir to paths sys.path.append(rootDir) 

Для меня это работает, но я чувствую, что это не пифонический. Я делаю что-то неправильно?

Должен ли я вместо этого всегда запускать package1.module1 из корня проекта? Если это так, это затрудняет запуск из IDE – мне нужно как-то установить пути в нем.

UPDATE: я попытался добавить файл root.pth в package1 с содержимым .. Но это не сработало – я предполагаю, что это предназначено для чего-то другого.

ВЫВОДЫ:

  1. Всегда используйте абсолютный импорт: import package1.module1

  2. Добавьте загрузчик в корневую папку, чтобы запустить некоторые из модулей в качестве автономного скрипта. Это решает запустить скрипт из среды IDE и является питоническим подходом.

22.04.07 Бретт Кэннон написал:

Этот PEP должен изменить if __name__ == "__main__": ... idiom, if __name__ == sys.main: ... так что у вас есть хотя бы возможность выполнить модуль в пакете, который использует относительный импорт.

Превратил этот PEP за идеи python. Остановили обсуждение там, когда предлагалось слишком много новых идей. =) Я перечислил все из них в разделе «Отклоненные идеи», хотя, если подавляющая поддержка одного из них идет вперед, PEP может перейти к одному из них.

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

– Гвидо ван Россум

3 Solutions collect form web for “Пути импорта – правильный путь?”

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

Итак, используя ваш пример:

 my_project/ main.py package1/ __init__.py module1 module2 package2/ __init__.py module1 module2 

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

 # in main.py from package1.module1 import * from package1.module2 import * # in package1.module1 import module2 from package2.module1 import * # in package2.module1 import * import module2 from package1.module1 import * 

Обратите внимание, что в приведенном выше пакете package1 и package2 зависят друг от друга. Этого никогда не должно быть. Но это всего лишь пример возможности импорта из любого места.

main.py тоже не должно быть ничем main.py . Это может быть очень просто:

 # main.py if __name__ == '__main__': from package1.module1 import SomeClass SomeClass().start() 

То, что я пытаюсь сделать, заключается в том, что если модуль должен быть доступен другим модулям, этот модуль должен быть доступен как импорт верхнего уровня. Модуль не должен ставить себя как импорт верхнего уровня (непосредственно на PYTHONPATH).

В обязанности проекта входит обеспечение того, чтобы весь импорт мог быть удовлетворен, если модуль включен непосредственно в проект. Есть два способа сделать это. Во-первых, создайте файл начальной загрузки, такой как main.py в папке проекта. Другой – это создание файла, который добавляет все соответствующие пути в PYTHONPATH, который загружается любыми точками входа, которые могут существовать.

Например:

 # setup.py import sys def load(): paths = ['/path1/','/path2/','/path3/'] for p in path: sys.path.insert(0, p) # entrypoint.py from setup import load load() # continue with program 

Главное, что нужно убрать, заключается в том, что модуль не должен ставить себя на путь. Путь должен определяться автоматически точкой входа в программу или явно определяться сценарием установки, который знает, где находятся все соответствующие модули.

Обычно я создаю каждый пакет как устанавливаемый пакет (т. Е. Создаю файл setup.py), а затем устанавливаю их в virtualenv только для этого проекта, используя pip.

Вы даже можете установить использование pip -e, если они все еще находятся в разработке.

Мне уже 5 лет здесь, но просто сделайте export PYTHONPATH=/path1:/path2: (обратите внимание на trailing ":") – таким образом ваш рабочий каталог (из которого вы запустите python) будет в пути.

  • Как проверить, существует ли модуль python, не импортируя его
  • Как проверить, был ли импортирован модуль python?
  • celery-django не может найти настройки
  • Оптимизирует ли python модули при импорте несколько раз?
  • Относительный импорт в Python 3
  • Импорт Python очень медленный - Anaconda python 2.7
  • Файл Pyspark import .py не работает
  • Почему Python запускает мой модуль, когда я его импортирую, и как его остановить?
  • Импортирование пакета с точным именем локально для модульного тестирования
  • Как и где установить модуль в python из github
  • Импорт модулей: __main__ vs import в качестве модуля
  • Python - лучший язык программирования в мире.