Как я могу добавить пути к переменным $ PYTHONPATH или $ PATH при выполнении скрипта в моем проекте python? - PullRequest
0 голосов
/ 29 октября 2019

У меня есть проект Python с несколькими сценариями (scriptA, scriptB, scriptC), который должен быть в состоянии найти пакеты, расположенные в подпути проекта, который не является пакетом или модулем python. Организация выглядит следующим образом:

|_project
  |_scriptA.py
  |_scriptB.py
  |_scriptC.py
  |_thrift_packages
    |_gen-py
        |_thriftA
          |__init__.py
          |_thriftA.py

Для каждого сценария я добавляю абсолютный путь к этому каталогу в sys.path

Есть ли способ изменить PYTHONPATH илиsys.path каждый раз, когда в проекте выполняется сценарий, чтобы мне не приходилось добавлять путь к этому каталогу к sys.path для каждого сценария?

Ответы [ 3 ]

1 голос
/ 29 октября 2019

У вас есть XY проблема , хотя и понятная, поскольку «правильный» способ разработки проекта Python неочевиден, и хороших руководств для начала работы не так много (естьтакже разные мнения по этому поводу, особенно в деталях, хотя я думаю, что то, что я опишу здесь, довольно распространено).

Во-первых, в корне вашего проекта вы можете создать setup.py. В наши дни этот файл может быть просто заглушкой;в конце концов необходимость в этом должна полностью исчезнуть, но некоторые инструменты все еще нуждаются в этом:

$ cat setup.py
#!/usr/bin/env python
from setuptools import setup
setup()

Затем создайте setup.cfg. Для большинства проектов Python этого должно быть достаточно - вам нужно только добавить дополнительный код в setup.py для особых случаев. Вот шаблон для более сложной setup.cfg, но для вашего проекта вам нужно как минимум:

$ cat setup.cfg
[metadata]
name = project
version = 0.1.0

[options]
package_dir =
    =thrift_packages/gen-py
packages = find:

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

$ mkdir -p ~/.virtualenvs
$ python3 -m venv ~/.virtualenvs/thrift
$ source ~/.virtualenvs/thrift/bin/activate

Теперь у вас должно появиться приглашение, которое выглядит примерно так(thrift) $ указывает на то, что вы находитесь в изолированной виртуальности. Здесь вы можете установить любые зависимости для вашего пакета, а также самого пакета, не мешая вашей основной установке Python.

Теперь установите ваш пакет в «редактируемом» режиме, что означает, что путь к исходным текстамАктивная разработка будет автоматически добавлена ​​в sys.path при запуске Python (включая ваши скрипты верхнего уровня):

$ pip install -e .

Если вы затем запустите Python и импортируете свой пакет, вы можете увидеть, например,что-то вроде:

$ python -c 'import thriftA'; print(thriftA)
<module 'thriftA' from '/path/to/your/source/code/project/thrift_packages/gen-py/thriftA/__init__.py'>

Если это кажется слишком большой проблемой, поверьте мне, это не так. Как только вы это освоите (и есть несколько шаблонов проектов, например, сделанных с помощью cookie-cutter , чтобы вы могли мыслить), вы увидите, что он делает такие вещи, как пути меньше беда). Вот так я запускаю любой нетривиальный проект (больше, чем один файл);если вы все настроите правильно, вам никогда не придется беспокоиться о суете с sys.path или $PYTHONPATH вручную.

В это руководство , хотя первая часть немного прикладнаяВ частности, если вы игнорируете конкретную цель этого кода, большая его часть на самом деле довольно общая, особенно в разделе «Упаковка нашего пакета», который более подробно повторяет некоторые из этих советов.

В качестве отступления,если вы уже используете conda, вам не нужно создавать virtualenv, поскольку среды conda - это просто причудливые virtualenvs.

Преимущество такого правильного подхода заключается в том, что когда приходит время установить ваш пакет, самостоятельно или пользователями, если ваши setup.cfg и setup.py настроены правильно, то все пользователи должны выполнить pip install . (без -e) и он должен работать так же.

0 голосов
/ 29 октября 2019

да, вы можете.

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

Вы можете получить текущую среду как dict (os.environ), скопировать ее в другой dict, изменить ее и передать в вызов supbprocess. (функции подпроцесса имеют параметр env)

import os
import subprocess
new_env = dict(os.environ)
new_env["PYTHONPATH"] = whateveryouwanthere  # add here the pythonpath that you want
cmd = ["mycmd.py", "myarg1", "myarg2"]  # replace with your command
subprocess.call(cmd, env=new_env)  #
# or alternatively if you also want to change the current directory
# subprocess.call(cmd, env=new_env, cwd=path_of_your_choice)  #
0 голосов
/ 29 октября 2019

Вы должны добавить __init__.py в каждый пакет, а затем правильно вызвать весь ваш скрипт.

|_project 
    |_scriptA.py 
    |_scriptB.py 
    |_scriptC.py 
    |__init__.py <====== Here
    |_thrift_packages 
        |__init__.py <====== Here
        |_gen-py 
        |_thriftA 
            |__init__.py 
            |_thriftA.py

Предполагая, что project находится в вашем pythonpath, вы можете сделать:

from project.thrift_packages.thriftA import thriftA
...