2010-12-11 22 views
6

Necesito ejecutar múltiples programas uno después de otro y cada uno se ejecuta en una ventana de consola. Quiero que la ventana de la consola sea visible, pero se crea una nueva ventana para cada programa. Esto es molesto porque cada ventana se abre en una nueva posición desde donde la otra se cierra y se roba el foco cuando se trabaja en Eclipse.¿Ejecuta varios programas secuencialmente en un símbolo del sistema de Windows?

Este es el código inicial que estaba usando:

def runCommand(self, cmd, instream=None, outstream=None, errstream=None): 
    proc = subprocess.Popen(cmd, stdin=instream, stdout=outstream, stderr=errstream) 

    while True: 
     retcode = proc.poll() 
     if retcode == None: 
      if mAbortBuild: 
       proc.terminate() 
       return False 
      else: 
       time.sleep(1) 
     else: 
      if retcode == 0: 
       return True 
      else: 
       return False 

me cambié a la apertura de una línea de comandos usando 'cmd' al llamar subprocess.Popen y luego llamar proc.stdin.write (b'program.exe \ r \ n '). Esto parece resolver el problema de una ventana de comando, pero ahora no puedo decir cuándo termina el primer programa y puedo comenzar el segundo. Quiero detener e interrogar el archivo de registro desde el primer programa antes de ejecutar el segundo programa.

¿Algún consejo sobre cómo puedo lograr esto? ¿Hay alguna otra opción para ejecutar los programas en una ventana que aún no he encontrado?

Respuesta

6

Dado que está utilizando Windows, puede crear un archivo por lotes que enumere cada programa que desea ejecutar y que se ejecutará en una sola ventana de consola. Como es un script por lotes, puede hacer cosas como poner enunciados condicionales en él, como se muestra en el ejemplo.

import os 
import subprocess 
import textwrap 

# create a batch file with some commands in it 
batch_filename = 'commands.bat' 
with open(batch_filename, "wt") as batchfile: 
    batchfile.write(textwrap.dedent(""" 
     python hello.py 
     if errorlevel 1 (
      @echo non-zero exit code: %errorlevel% - terminating 
      exit 
     ) 
     time /t 
     date /t 
    """)) 

# execute the batch file as a separate process and echo its output 
kwargs = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 
       universal_newlines=True) 
with subprocess.Popen(batch_filename, **kwargs).stdout as output: 
    for line in output: 
     print line, 

try: os.remove(batch_filename) # clean up 
except os.error: pass 
+0

que casi con trabajar. Básicamente, hice lo mismo escribiendo en el símbolo del sistema que me abrí. Pero el problema es que no puedo parar después de que el primer comando haya terminado, inspeccionar un archivo de registro y luego pasar al siguiente comando. – Sean

+0

@Sean: parece que podría intercalar invocaciones de sus comandos con una que le permitió inspeccionar el archivo de registro y determinar un código de salida que el archivo por lotes puede inspeccionar y usar para determinar si 'salir' o continuar. Los programas por lotes admiten el procesamiento condicional 'if [not] errorlevel ...'. Si está interesado, podría actualizar mi respuesta para mostrar cómo se podría hacer eso. – martineau

+0

Gracias Martineau. Hice una búsqueda rápida en errorlevels y archivos por lotes y lo encontré. ¡Gracias por la ayuda! – Sean

0

En la sección 17.5.3.1. constantes en el subproceso documentación módulo hay description de subprocess.CREATE_NEW_CONSOLE constante:

El nuevo proceso tiene una nueva consola, en lugar de heredar consola de su padre (el valor por defecto).

Como vemos, de forma predeterminada, el nuevo proceso hereda la consola principal. La razón por la que observa que se abren varias consolas es el hecho de que llama a las secuencias de comandos desde Eclipse, que no tiene consola, por lo que cada subproceso crea su propia consola ya que no hay una consola que pueda heredar. Si alguien desea simular este comportamiento, es suficiente ejecutar un script de Python que crea subprocesos usando pythonw.exe en lugar de python.exe. La diferencia entre los dos es que el primero no abre una consola, mientras que el segundo sí lo hace.

La solución es tener un script de ayuda - llamémoslo lanzador - que, de forma predeterminada, crea la consola y ejecuta los programas en subprocesos. De esta forma, cada programa hereda una y la misma consola de su principal: el iniciador . Para ejecutar programas secuencialmente utilizamos el método Popen.wait().

--- --- script_run_from_eclipse.py

import subprocess 
import sys 

subprocess.Popen([sys.executable, 'helper.py']) 

--- --- helper.py

import subprocess 

programs = ['first_program.exe', 'second_program.exe'] 
for program in programs: 
    subprocess.Popen([program]).wait() 
    if input('Do you want to continue? (y/n): ').upper() == 'N': 
     break 
Cuestiones relacionadas