Запуск подпроцесса внутри разных virtualenv с python - PullRequest
22 голосов
/ 08 ноября 2011

Допустим, у меня есть 2 разные версии моего приложения, установленные в 2 разных виртуальных средах.myapp v1.0 и myapp v2.0.

Теперь я хотел бы сравнить их.Сравнение написано на самом Python.Каков был бы лучший способ сделать это?Давайте предположим, что я могу запустить их по отдельности и записать оба выходных файла, которые я могу сравнить позже.

Один из способов сделать это - написать скрипт bash (это то, что у меня есть в настоящее время).Я активирую один virtualenv, запускаю myapp v1.0, активирую другой virtualenv, запускаю myapp v2.0.Позже запустите модуль сравнения этих файлов.Но я хотел бы добавить еще немного динамики (с некоторыми дополнительными аргументами и т. Д.), Что было бы проще с python.

Edit:

В настоящее время у меня есть что-то подобное (скрипт bash):

source virtualenv1/bin/activate
python my_script.py
deactivate

source virtualenv2/bin/activate
python my_other_script.py
deactivate

python my_comparison_script.py

Вместо этого я хотел бы сделать только:

python my_comparison_script.py

, и мои сценарии будут выполняться внутри этого.

Ответы [ 4 ]

33 голосов
/ 25 ноября 2014

Принятый ответ не решает проблему «активации» virtualenv в подпроцессе.

Если вы запускаете ваше приложение с помощью вызова исполняемого файла python, как в вашем примере, это на самом деле очень просто: вам нужно только явно указать исполняемый файл в virtualenv.

import subprocess

subprocess.Popen(["virtualenv1/bin/python", "my_script.py"])
subprocess.Popen(["virtualenv2/bin/python", "my_other_script.py"])

запустит процессы в соответствующих virtualenvs.

Важно

Для решения проблем, озвученных в комментариях:

Если вы хотите запустить подпроцесс и обязательно использовать тот же интерпретатор , в котором выполняется текущий процесс, вы должны использовать sys.executable . Также доступно: sys.exec_prefix для доступа к префиксу каталога для конкретного сайта, где установлены зависящие от платформы файлы Python.

Если вы хотите более углубленно обсудить эту тему, взгляните на этот запрос на извлечение .

2 голосов
/ 03 августа 2018

Простой вариант - запустить серию команд с подпроцессом следующим образом.

import subprocess

subprocess.call('source activate my_virtualenv; python my_script.py', shell=True)

И повторить при необходимости.

1 голос
/ 01 февраля 2019

Я думаю, virtualenv документация это хорошо объясняет.

TL; DR

Запуск двоичного файла pyv venv напрямую НЕ - это то же самое, что активация venv. Вы также должны изменить PATH и VIRTUAL_ENV переменные соответственно (смотрите os.environ )

Источник

$ source / path / to / ENV / bin / activ

Это изменит ваш $ PATH, поэтому его первая запись - это virtualenv bin / каталог. (Вы должны использовать источник, потому что он меняет вашу оболочку окружающая среда на месте.) Это все, что она делает; это просто удобство.

Если вы напрямую запускаете скрипт или интерпретатор python из Каталог bin / virtualenv (например, путь / к / ENV / bin / pip или /path/to/ENV/bin/python-script.py), тогда sys.path будет автоматически установить использование библиотек Python, связанных с virtualenv. Но, в отличие от сценариев активации, переменные среды PATH и VIRTUAL_ENV не будет изменен. Это означает, что если ваш Python сценарий использует, например, подпроцесс для запуска другого скрипта Python (например, через ! / usr / bin / env строка python shebang) второй скрипт не может быть выполнен с тем же двоичным файлом Python, что и первый, и не может иметь одинаковый доступные для него библиотеки. Чтобы этого не случилось, ваш первый скрипт нужно будет изменить переменные среды так же, как сценарии активации перед выполнением второго сценария.

0 голосов
/ 08 ноября 2011

в чем именно вопрос?Как использовать подпроцесс для выполнения команд оболочки?в этом случае некоторый упрощенный псевдокод может выглядеть следующим образом:

import subprocess

myProcess = subprocess.Popen(   ['these', 'are', 'for', 'the', 'shell'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE )

[outStream, errStream] = myProcess.communicate()

, тогда вы можете делать все, что захотите, с standard out (outStream) и делать разные вещи, если существует errStream (standardошибка).это включает запись стандартной или стандартной ошибки в файл.тогда я предполагаю, что вы разошлись бы по этим файлам?

реальный пример кода (при условии, что у вас есть python 2.6+ в системе linux) может выглядеть так:

import subprocess

with open('dateHelp.log', 'w') as dateLog:
    with open('dateHelp.err', 'w') as errLog:
        dateHelp = subprocess.Popen([ 'date', '-h'], stdout=dateLog, 
                                                     stderr=errLog)
        dateHelp.communicate()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...