Асинхронные фоновые процессы в Python?

Я использовал это как ссылку, но не смог выполнить именно то, что мне нужно: Вызов внешней команды в Python

Я также читал это: http://www.python.org/dev/peps/pep-3145/

Для нашего проекта у нас есть 5 svn проверок, которые необходимо обновить, прежде чем мы сможем развернуть наше приложение. В моей среде разработчиков, где быстрое развертывание является более важным для производительности, чем производственное развертывание, я работаю над ускорением процесса.

У меня есть bash script, который работает прилично, но имеет некоторые ограничения. Я запускаю несколько обновлений svn со следующей командой bash:

(svn update /repo1) & (svn update /repo2) & (svn update /repo3) &

Все они работают параллельно и работают очень хорошо. Я также использую этот шаблон в остальной части сборки script для выключения каждой сборки ant, а затем перемещения войн в Tomcat.

Однако у меня нет контроля над остановкой развертывания, если одно из обновлений или сборки не работает.

Я переписываю мой bash script с Python, поэтому у меня больше контроля над ветвями и процессом развертывания.

Я использую subprocess.call(), чтобы скрыть команды 'svn update/repo', но каждый из них действует последовательно. Я пытаюсь (svn update/repo) & ' и все они срабатывают, но код результата немедленно возвращается. Поэтому у меня нет способа определить, сбой какой-либо конкретной команды или нет в асинхронном режиме.

import subprocess

subprocess.call( 'svn update /repo1', shell=True )
subprocess.call( 'svn update /repo2', shell=True )
subprocess.call( 'svn update /repo3', shell=True )

Мне бы очень хотелось найти способ увольнения Python каждой команды Unix, и если какой-либо из вызовов не удастся в любой момент, останавливается весь script.

Ответ 1

Не используйте shell=True. Не нужно вызывать оболочку для вызова вашей программы svn, и это даст вам код возврата оболочки вместо svn's.

repos = ['/repo1', '/repo2', '/repo3']
# launch 3 async calls:
procs = [subprocess.Popen(['svn', 'update', repo]) for repo in repos]
# wait.
for proc in procs:
    proc.wait()
# check for results:
if any(proc.returncode != 0 for proc in procs):
    print 'Something failed'