Подпроцесс Python/Popen с измененной средой

Я считаю, что запуск внешней команды со слегка измененной средой - очень распространенный случай. Вот как я это делаю:

import subprocess, os
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)

У меня есть ощущение, что есть лучший способ; это выглядит хорошо?

Ответ 1

Я думаю, что os.environ.copy() лучше, если вы не собираетесь изменять os.environ для текущего процесса:

import subprocess, os
my_env = os.environ.copy()
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)

Ответ 2

Это зависит от проблемы. Если он клонировать и модифицировать среду, одним из решений может быть:

subprocess.Popen(my_command, env=dict(os.environ, PATH="path"))

Но это несколько зависит от того, что замененные переменные являются действительными идентификаторами python, которые они чаще всего (как часто вы используете имена переменных среды, которые не являются буквенно-цифровыми + подчеркивание или переменными, начинающиеся с числа?).

В противном случае вы можете написать что-то вроде:

subprocess.Popen(my_command, env=dict(os.environ, 
                                      **{"Not valid python name":"value"}))

В очень странном случае (как часто вы используете контрольные коды или символы не-ascii в именах переменных среды?), что ключи среды bytes вы не можете (на python3) даже использовать эту конструкцию.

Как вы можете видеть, используемые методы (особенно первый), используемые здесь преимуществами для ключей среды, обычно являются действительными идентификаторами python, а также известны заранее (во время кодирования), второй подход имеет проблемы. В тех случаях, когда это не так, вам, вероятно, следует искать другой подход.

Ответ 3

вы можете использовать my_env.get("PATH", '') вместо my_env["PATH"] в случае, если PATH каким-то образом не определено в исходной среде, но отличное от него выглядит нормально.

Ответ 4

С Python 3.5 вы можете сделать это следующим образом:

import os
import subprocess

my_env = {**os.environ, 'PATH': '/usr/sbin:/sbin:' + os.environ['PATH']}

subprocess.Popen(my_command, env=my_env)

Здесь мы получим копию os.environ и переопределенного значения PATH.

Это стало возможным благодаря PEP 448 (Дополнительные распаковки обобщений).

Другой пример. Если у вас есть среда по умолчанию (т.е. os.environ) и dict, с которым вы хотите переопределить значения по умолчанию, вы можете выразить это следующим образом:

my_env = {**os.environ, **dict_with_env_variables}

Ответ 5

Чтобы временно установить переменную окружения без копирования объекта os.envrion и т.д., я делаю следующее:

process = subprocess.Popen(['env', 'RSYNC_PASSWORD=foobar', 'rsync', \
'rsync://[email protected]::'], stdout=subprocess.PIPE)

Ответ 6

Параметр env принимает словарь. Вы можете просто взять os.environ, добавить ключ (вашу желаемую переменную) (к копии dict, если вам нужно), и использовать его как параметр для Popen.

Ответ 7

Я знаю, что на это был дан ответ в течение некоторого времени, но есть некоторые моменты, которые некоторые могут захотеть узнать об использовании PYTHONPATH вместо PATH в своей переменной окружения. Я изложил объяснение запуска скриптов python с cronjobs, который имеет дело с измененной средой по-другому (здесь). Думал, что это будет полезно для тех, кто, как и я, нуждался в чуть больше, чем этот ответ.

Ответ 8

Я использовал подпроцесс из программного обеспечения Maya, где у него был собственный интерпретатор. Изменив путь python внутри Maya, я могу запустить его с помощью выбранной вами установки и библиотек python.

import os
import subprocess

os.environmnet["PYTHONPATH"] = "C:/Python27"
command = "C:/Python27/python.exe d:/mypyfile.py args"
subprocess.Popen(command)

Как только я закончу запуск в этой среде, я снова могу вернуться к интерпретатору Maya, сбросив "PYTHONPATH"

Ответ 9

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