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

Я знаю, что есть много похожих или одинаковых вопросов, но я все еще не могу понять / найти правильный способ для работы с модулями. 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 может сломать другой?
  • Пакет Cython с __init __. Pyx: Возможно?
  • Является ли `import module` лучшим стилем кодирования, чем` из функции импорта модуля '?
  • ImportError: нет модуля с именем mpl_toolkits с maptlotlib 1.3.0 и py2exe
  • Можно ли настроить Python для кэширования поиска в каталоге sys.path?
  • Как unimport модуль python, который уже импортирован?
  • Конфликт импорта Python
  • Как я могу переопределить константу в импортированном модуле Python?
  •  
    Interesting Posts for Van-Lav

    Общение между Autohotkey и python

    Django REST Framework: SlugRelatedField для косвенного атрибута?

    Динамическая загрузка некомпилированных плагинов python в код компиляции py2exe

    сериализация результата запроса с json вызывает ошибку:

    Почему приложение PyQt открыто в фоновом режиме на Mac OS X?

    Рекурсивно dir () объект python для поиска значений определенного типа или с определенным значением

    Как я могу получить dict из запроса sqlite?

    Возвращение уникальных совпадений с использованием regex в python

    Как преобразовать долготу и широту в адрес улицы

    Задача django-celery-email не выполняется

    Python mysqldb: библиотека не загружена: libmysqlclient.18.dylib

    Использование многопроцессорной обработки / потоковой обработки для прерывания работы массива numpy в кусках

    argparse необязательный аргумент перед позиционным аргументом

    Комбинации строки с конкретными переменными

    Ошибка при запуске endpointscfg.py get_swagger_spec

    Python - лучший язык программирования в мире.