2014-09-15 9 views
0

Мне нужно запустить много команд bash из Python. На данный момент я делаю это с
subprocess.Popen (cmd, shell = True)Предотвращение создания нового дочернего процесса с использованием подпроцесса в Python

Есть ли какое-либо решение для запуска всех этих команд в той же оболочке? subprocess.Popen открывает новую оболочку при каждом выполнении, и мне нужно настроить все необходимые переменные при каждом вызове, чтобы команда cmd работала правильно.

+0

Каждая выполняемая вами команда все еще является подпроцессом и дочерним процессом либо вашего скрипта, либо оболочки, которая была порождена вашим скриптом. Вам нужна оболочка между вашим ребенком и вашим скриптом? – soulseekah

+0

В каждом подпроцессе.Popen мне нужно экспортировать переменную и запустить команду cmd в том же вызове. Это приведет к уродливому синтаксису. Было бы здорово экспортировать эту переменную только один раз и после этого запустить мои команды cmd. –

+0

Если вам не нужно использовать 'subprocess.Popen()', вы должны использовать 'multiprocessing.Process'. (Все ли ваши вакансии независимы и ненасильны?Вам нужно беспокоиться о том, чтобы перехватить ненулевой статус ошибки в середине вашей последовательности заданий?) – smci

ответ

-1

Используйте вместо этого multiprocessing, он более легкий и эффективный.

В отличие от subprocess.Popen он не открывает новую оболочку при каждом выполнении.

Вы не сказали, что вам нужен для запуска subprocess.Popen, и вам это может не понадобиться; вы только что сказали, что это то, что вы сейчас делаете. Больше оправдания, пожалуйста.

См. set env var in Python multiprocessing.Process о том, как установить env vars раз и навсегда в родительском процессе.

+1

Можете ли вы объяснить, как «многопроцессорство» на самом деле будет полезно здесь? – dano

+0

Потому что в отличие от subprocess.Popen он не открывает новую оболочку при каждом выполнении, о чем жаловался OP. Считаете ли вы, что вы не отвечаете правильными ответами? Это досадно и разрушительно. – smci

+1

Я не спустил вниз. 'subprocess.Popen' выполняет дочерний процесс. 'multiprocessing.Process' выполняет вызов python (как функцию) в другом процессе. Как бы вы использовали 'multiprocessing.Process' для выполнения кучи команд bash в одной оболочке, как хочет OP? – dano

1

Почему бы просто не создать сценарий оболочки со всеми командами, которые необходимо выполнить, а просто использовать один вызов subprocess.Popen() для его запуска? Если содержимое команд, которые нужно запустить, зависит от результатов, вычисленных в вашем сценарии Python, вы можете просто создать сценарий оболочки динамически, а затем запустить его.

+0

Мои команды разделены другими операциями python. Я не знаю, как это можно сделать, но я полагаю, что это приведет к сложному синтаксису. –

+0

Наличие только одной оболочки по-прежнему хуже нуля. Я не вижу причин, почему мы не можем иметь нулевые оболочки - вызывать каждую команду с явным массивом argv и, следовательно, (неявно) 'shell = False'. –

2

subprocess.Popen позволяет вам поставлять словарь переменных окружения, который станет средой для выполняемого процесса. Если единственная причина, по которой вам нужен shell=True, - установить переменную окружения, тогда я предлагаю вместо этого использовать явный словарь среды; это безопаснее и не особенно сложно. Кроме того, обычно проще создавать вызовы команд, когда вам не нужно беспокоиться о метасимволах и метасимволах оболочки.

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

Если вы можете изменить свою собственную среду с настройками, просто сделайте это :

os.environ['theEnvVar'] = '/the/value' 

Тогда вы можете просто использовать простой Popen.call (или аналогичный), чтобы запустить команду:

output = subprocess.check_output(["ls", "-lR", "/tmp"]) 

Если по каким-либо причинам вы не можете изменить свое собственное окружение, вам нужно сделать копию текущую среду, изменить ее по желанию и передать ее каждому subprocess.call:

env = os.environ.copy() 
env['theEnvVar'] = '/the/value' 
output = subprocess.check_output(["ls", "-lR", "/tmp"], env=env) 

Если вы не хотите, чтобы указать env=env каждый раз, просто написать небольшой класс-обертку.

Смежные вопросы