2015-09-21 6 views
-1

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

Так что мой код что-то вроде этого:

# multiple files 
for file in files: 
    P1 = Popen('python Prog1.py' + ' ' + file, stdout=PIPE , stderr=STDOUT,shell=True) 
    # Now I want to capture the output to files so can be used for the next process 
    # It didn't work 
    l_out_files.append(P1.stdout) 
    # Prog2 require if the input file is more than one to have them separated by space 
P2 = Popen('python Prog2.py' + ' ' + ' '.join(l_out_files), stdout=PIPE , stderr=STDOUT,shell=True) 

Большое спасибо, ребята,

Лучшие

+0

, что вы на самом деле пытаетесь передать, оба p1 и p2 в петле? –

+0

@PadraicCunningham Я исправил это, p1 входит в цикл, но бит p2. – BioInformatician

+0

, поэтому Prog2.py берет строку имен файлов? Также почему бы не просто сделать все это из python, каковы ваши программы на самом деле? –

ответ

2

Насколько ваш собственный код идет добавление P1.stdout, только добавляет ссылки на метод ваш список так очевидно, что не будет работать, было бы P1.communicate()[0], чтобы извлечь результат.

Я полагаю, все это может быть сделано без необходимости подпроцесса, но вы можете создать список продукции с check_output, на самом деле не знаю, почему вы перенаправляют поток ошибок в STDOUT либо:

from subprocess import check_output,STDOUT 

data = [check_output(['python', 'Prog1.py', file], stderr=STDOUT) for file in files] 

out = check_output(['python', 'Prog2.py',' '.join(data)], stderr=STDOUT) 

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

Чтобы поймать любые ошибки, вы можете использовать Try/за исключением поймать CalledProcessError:

from subprocess import check_output,STDOUT, CalledProcessError 

data = [] 
for file in files: 
    try: 
     data.append(check_output(['python', 'Prog1.py'], stderr=STDOUT)) 
    except CalledProcessError as e: 
     print(e.message) 
+0

Это не сработало. Prog1 отображает некоторые сообщения для того, чтобы пользователь мог уведомить их о состоянии анализа и т. Д., Сообщения, записанные только с помощью check_output, но не фактический вывод, который в Prog1 записывается в файл. – BioInformatician

+0

Как вы можете уловить вывод, записанный в файл? Вам нужно добавить то, что делает ваш код на самом деле, и именно то, что вы ожидаете от –

+0

использовать '' Prog2.py '] + имена файлов' вместо '' Prog2.py ',' .join (data)]' если вы думаете что 'Prog1.py' записывает имя файла, где он сохраняет свой результат в stdout – jfs

0

Похоже, что вы хотите подражать bash process substitution:

#!/usr/bin/env python 
from subprocess import check_call 

check_call('prog2 <(prog1 file1) <(prog1 file2) <(prog1 file3) ...', 
      shell=True, executable='/bin/bash') 

где это prog2 бежит python Prog2.py, prog1 прогонов python Prog1.py. Предполагается, что prog1 записывает свой результат в stdout, а prog2 принимает входные имена файлов в командной строке. Подстановка Bash-процесса позволяет передавать выходные данные от prog1 до prog2, не записывая данные на диск и не накапливая их в памяти (в случае, если она может быть большой).

Хотя вы можете сделать это в чистом Python без оболочки (the link shows named pipe-based and fdescfd (/dev/fd/#) -based solutions, но при необходимости вы можете использовать другие методы); было бы проще, если prog2 будет принимать входные данные на стандартном вводе:

#!/usr/bin/env python 
from subprocess import check_call 

check_call('{ prog1 file1; prog1 file2; prog1 file3; ...; } | prog2', 
      shell=True) 

Вы можете сделать это в чистом Python без оболочки:

#!/usr/bin/env python3 
from subprocess import Popen, PIPE, check_call 

with Popen('prog2', stdin=PIPE) as prog2: 
    for filename in files: 
     check_call(['prog1', filename], stdout=prog2.stdin)