Как управлять sys.path в Python для проекта системно-независимым способом

#python #sys #python-venv #sys.path

#python #sys #python-venv #sys.path

Вопрос:

У меня есть каталог проекта, который выглядит следующим образом

 /work
    /venv
    /project1
        app.py
        /package1
        /package2
        etc
  

где скрипт app.py управляет проектом, над которым я работаю. Когда я запускаю
python -m site из /project1 каталога, я получаю, как и ожидалось

 sys.path = [
    '/work/project1',
  

плюс соответствующие /lib/pythonX.Y пути. Однако при запуске app.py (из project1) этот импорт

 from package1 import ...
  

сбой с ModuleNotFoundError, в то from .package1 import ... время как работает нормально, поскольку он сообщает python для поиска каталога, который app.py находится внутри. Итак, я добавил это в начало app.py

 import sys
print(sys.path)
  

и в результате получается

 sys.path = [
    '/work',
  

Вместо /work/project1 каталога, в котором выполняется поиск при импорте в app.py есть /work . В чем причина этого несоответствия между python -m site и print(sys.path) и каков наилучший способ убедиться, что /work/project1 это всегда часть sys.path?

Я бы хотел избежать использования чего-то подобного site.addsitedir() и, возможно, вместо этого использовать файл .pth. Из того, что я прочитал, хотя файл .pth принадлежит /lib/pythonX.Y/sitepackages , но мне также нужно, чтобы это решение было независимым от системы, чтобы сотруднику, который клонирует /project1 из github, не нужно было добавлять свой собственный файл .pth.

Ответ №1:

Я не знаю, применимо ли это к вам, но я помог многим другим, указав, что делает наш магазин. Мы вообще не беспокоимся о пути при выполнении. Все, на что мы полагаемся, это то, что из начального местоположения скрипта мы знаем, где находятся все зависимости. Затем мы добавляем каталоги в sys.path, вычисляя их позиции относительно каталога, содержащего исходный скрипт, который всегда доступен.

Мы помещаем эту логику в файл с именем init.py в том же каталоге, что и основной скрипт. Вот как это выглядит:

 repoPath = os.path.dirname(__file__)   "/../../Development/repo1"
sys.path.append(repoPath   "/common/common-pyutil")
sys.path.append(repoPath   "/common/common-pyutil/thirdparty")
  

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