Я выполняю несколько команд, которые могут занять некоторое время параллельно на машине Linux с Python 2.6.
Итак, я использовал класс subprocess.Popen
и метод process.communicate()
для распараллеливания выполнения множественного числа.Команда группирует и захватывает вывод сразу после выполнения.
def run_commands(commands, print_lock):
# this part runs in parallel.
outputs = []
for command in commands:
proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
output, unused_err = proc.communicate() # buffers the output
retcode = proc.poll() # ensures subprocess termination
outputs.append(output)
with print_lock: # print them at once (synchronized)
for output in outputs:
for line in output.splitlines():
print(line)
В другом месте это называется так:
processes = []
print_lock = Lock()
for ...:
commands = ... # a group of commands is generated, which takes some time.
processes.append(Thread(target=run_commands, args=(commands, print_lock)))
processes[-1].start()
for p in processes: p.join()
print('done.')
Ожидаемый результат состоит в том, что каждый вывод группы командотображается сразу, в то время как их выполнение выполняется параллельно.
Но из второй выходной группы (конечно, поток, который становится вторым, изменяется из-за планирования неопределенности), он начинает печатать без перевода строки и добавленияпробелы, равные количеству символов, напечатанных в каждой предыдущей строке, и входное эхо отключено - состояние терминала «искажено» или «сбой».(Если я запускаю команду оболочки reset
, она восстанавливается нормально.)
Сначала я попытался найти причину обработки '\r'
, но это не было причиной.Как вы видите в моем коде, я обработал его правильно, используя splitlines()
, и я подтвердил, что с помощью функции repr()
, примененной к выводу.
Я думаю, что причина заключается в одновременном использовании каналов в Popen
иcommunicate()
для stdout / stderr.Я пробовал check_output
метод ярлыков в Python 2.7, но безуспешно.Конечно, описанная выше проблема не возникает, если я сериализую все команды и распечатки команд.
Есть ли лучший способ обрабатывать Popen
и communicate()
параллельно?