Регистрация выходных данных файла и времени ожидания с Python - PullRequest
1 голос
/ 11 февраля 2011

Я просматриваю большой список файлов и запускаю команду для всех из них.Я хочу записать вывод, и если команда занимает более 5 минут для файла, я хотел бы остановить команду и перейти к следующему файлу.

У меня две проблемы:

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

  2. Я не уверен, как я могу опросить процесс и выйти из него через 5 минут и перейти к следующему файлу.

Ниже приведен упрощенный код:

import os, fnmatch
import subprocess
import sys
f=open('filenames','w')

'Locate all files matching supplied filename pattern in and below supplied root directory.'''

def locate(pattern, root=os.curdir):        
    for path, dirs, files in os.walk(os.path.abspath(root)):
        for filename in fnmatch.filter(files, pattern):
            yield os.path.join(path, filename)


for filename in locate("*.dll"):
    f.write(filename)   
    #cmd defintion is changed for simplicity 
    cmd='cat %s' %filename
    p=subprocess.Popen(cmd,stdout=f)   
    p.communicate()[0]

Ответы [ 2 ]

1 голос
/ 11 февраля 2011
  1. Использовать f.flush() после f.write(filename).
  2. См. Использование модуля 'подпроцесс' с таймаутом
1 голос
/ 11 февраля 2011

Вот то, что я использую, примерно:

from datetime import datetime
from time import time

import subprocess
import sys
import threading
import os

class Execution(threading.Thread):
  comm = None
  proc = None
  returncode = None
  stdoutdata = None
  stderrdate = None

  def __init__(self, comm):
    threading.Thread.__init__(self)
    self.comm = comm

  def run(self):
    self.proc = subprocess.Popen(self.comm, bufsize=-1, stdin=None,  
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    self.proc.wait()
    (self.stdoutdata, self.stderrdata) = self.proc.communicate()
    self.returncode = self.proc.poll()

for curcommand in somecommandlist:
  ex = Execution(curcommand)
  starttime = time()
  ex.start()
  ex.join(some_timeout_in_seconds)

  wastimeout = False
  if (ex.isAlive()):
    wastimeout = True
    print("TIMEOUT OCCURRED @ %s" % (datetime.today(),))
    ex.proc.kill()

  ex.join()
  endtime = time()
  duration = endtime - starttime
  print("DURATION %s" % (duration,))

  exitcode = ex.returncode
  print("EXIT CODE: %s" % (exitcode,))
  print somepostprocessing(ex.stdoutdata,ex.stderrdata)
  sys.stdout.flush()

По сути: запустить процесс в отдельном потоке.Это необходимо, потому что модуль threading дает вам время ожидания, а модуль subprocess - нет.Подождите до истечения времени ожидания;проверьте, жива ли нить.Если поток работает, мы прекращаем его, убивая процесс (здесь subprocess дает вам конструкцию kill(), а threading - нет) и ожидая завершения потока самостоятельно.

Имейте в виду, что communicate() блокирует и сохраняет вывод full дочерних stderr и stdout, поэтому это может не сработать, если вывод очень большой.

...