Передача выходных данных подпроцесса. Открыть в файлы - PullRequest
43 голосов
/ 25 февраля 2010

Мне нужно запустить несколько длительных процессов с subprocess.Popen, и я бы хотел, чтобы stdout и stderr от каждого автоматически передавались по конвейеру в отдельные файлы журнала. Каждый процесс будет выполняться одновременно в течение нескольких минут, и я хочу, чтобы два файла журнала (stdout и stderr) для процесса были записаны при запуске процессов.

Нужно ли постоянно вызывать p.communicate() для каждого процесса в цикле, чтобы обновить каждый файл журнала, или есть какой-то способ вызвать исходную команду Popen, чтобы stdout и stderr автоматически ли открывать файловые дескрипторы?

Ответы [ 3 ]

69 голосов
/ 25 февраля 2010

Вы можете передать stdout и stderr в качестве параметров Popen()

subprocess.Popen(self, args, bufsize=0, executable=None, stdin=None, stdout=None,
                 stderr=None, preexec_fn=None, close_fds=False, shell=False,
                 cwd=None, env=None, universal_newlines=False, startupinfo=None, 
                 creationflags=0)

Например

>>> import subprocess
>>> with open("stdout.txt","wb") as out, open("stderr.txt","wb") as err:
...    subprocess.Popen("ls",stdout=out,stderr=err)
... 
<subprocess.Popen object at 0xa3519ec>
>>> 
36 голосов
/ 25 февраля 2010

за документы ,

stdin, stdout и stderr определяют стандартный ввод выполненных программ, стандартный вывод и стандартная ошибка файловые дескрипторы соответственно. действительный значения - ТРУБА, существующий файл дескриптор (положительное целое число), существующий файловый объект, и None.

Так что просто передайте открытые для записи файловые объекты как именованные аргументы stdout= и stderr=, и все будет в порядке!

2 голосов
/ 23 сентября 2010

Я одновременно запускаю два подпроцесса и сохраняю вывод обоих в один файл журнала. Я также встроил тайм-аут для обработки зависших подпроцессов. Когда выходные данные становятся слишком большими, тайм-аут всегда срабатывает, и ни один из stdout из любого подпроцесса не сохраняется в файле журнала. Ответ, изложенный Алексеем выше, не решает его.

# Currently open log file.
log = None

# If we send stdout to subprocess.PIPE, the tests with lots of output fill up the pipe and
# make the script hang. So, write the subprocess's stdout directly to the log file.
def run(cmd, logfile):
   #print os.getcwd()
   #print ("Running test: %s" % cmd)
   global log
   p = subprocess.Popen(cmd, shell=True, universal_newlines = True, stderr=subprocess.STDOUT, stdout=logfile)
   log = logfile
   return p


# To make a subprocess capable of timing out
class Alarm(Exception):
   pass

def alarm_handler(signum, frame):
   log.flush()
   raise Alarm


####
## This function runs a given command with the given flags, and records the
## results in a log file. 
####
def runTest(cmd_path, flags, name):

  log = open(name, 'w')

  print >> log, "header"
  log.flush()

  cmd1_ret = run(cmd_path + "command1 " + flags, log)
  log.flush()
  cmd2_ret = run(cmd_path + "command2", log)
  #log.flush()
  sys.stdout.flush()

  start_timer = time.time()  # time how long this took to finish

  signal.signal(signal.SIGALRM, alarm_handler)
  signal.alarm(5)  #seconds

  try:
    cmd1_ret.communicate()

  except Alarm:
    print "myScript.py: Oops, taking too long!"
    kill_string = ("kill -9 %d" % cmd1_ret.pid)
    os.system(kill_string)
    kill_string = ("kill -9 %d" % cmd2_ret.pid)
    os.system(kill_string)
    #sys.exit()

  end_timer = time.time()
  print >> log, "closing message"

  log.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...