web-dev-qa-db-fra.com

Piping de la sortie du sous-processus. Ouverture aux fichiers

J'ai besoin de lancer un certain nombre de processus de longue durée avec subprocess.Popen, Et je voudrais que les stdout et stderr de chacun soient automatiquement redirigés vers des fichiers journaux séparés. Chaque processus s'exécutera simultanément pendant plusieurs minutes et je souhaite que deux fichiers journaux (stdout et stderr) par processus soient écrits pendant l'exécution des processus.

Dois-je appeler en permanence p.communicate() sur chaque processus dans une boucle afin de mettre à jour chaque fichier journal, ou existe-t-il un moyen d'invoquer la commande _ Popen d'origine afin que stdout et stderr sont automatiquement diffusés en continu pour ouvrir les descripteurs de fichiers?

44
user280867

Par les docs ,

stdin, stdout et stderr spécifient respectivement les descripteurs d'entrée standard, de sortie standard et de fichier d'erreur standard des programmes exécutés. Les valeurs valides sont PIPE, un descripteur de fichier existant (un entier positif), un objet fichier existant et Aucun.

Il suffit donc de passer les objets fichier ouverts pour l'écriture en tant qu'arguments nommés stdout= et stderr= et ça devrait aller!

36
Alex Martelli

Vous pouvez passer stdout et stderr comme paramètres à 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)

Par exemple

>>> 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>
>>> 
72
John La Rooy

J'exécute simultanément deux sous-processus et j'enregistre la sortie des deux dans un seul fichier journal. J'ai également intégré un délai d'attente pour gérer les sous-processus bloqués. Lorsque la sortie devient trop volumineuse, le délai d'expiration se déclenche toujours et aucune des sorties standard de l'un ou l'autre des sous-processus n'est enregistrée dans le fichier journal. La réponse posée par Alex ci-dessus ne le résout pas.

# 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()
2
jasper77