[pyar] Ejecutando algo y enterándome qué pasa

Ezequiel Garcia elezegarcia en gmail.com
Mie Nov 21 14:11:44 ART 2012


2012/11/21 Facundo Batista <facundobatista en gmail.com>:
> 2012/11/21 Facundo Batista <facundobatista en gmail.com>:
>
>> Situación: tengo un string y debo ejecutarlo en la máquina (esto es
>> bajo linux, para Launcherposta [0]).
>>
>> Ejemplo: "/usr/bin/gvim /home/facundo/fruta.txt"
>>
>> Quiero ejecutar ese string (del cual no tengo control) y si hay un
>> error, indicárselo al usuario.
>>
>> Probé con
>>
>> a) subprocess.Popen(cmd, shell=True) -- el problema acá es que si el
>> shell no encuentra el proceso, *yo no me entero* (no salta una
>> excepción a nivel de Python)
>>
>> b) subprocess.Popen(cmd) -- acá no encuentra el comando, directamente;
>> para que lo encuentre debería pasar cmd.split(), pero el tema es que
>> hacer un split() a ciegas me puede convertir un comando que es
>> "/bin/algo -t 3 foobar" en ["/bin/algo", "-t", "3", "foobar"] cuando
>> realmente debería ser ["/bin/algo", "-t 3", "foobar"] (bah, creo).
>>
>> Puntos extras por tener el process id de lo que lancé, así lo logueo.
>
> Gracias por los aportes a todos! Buscando un poco más, y siguiendo
> links que me pasaron... terminé en la documentación de Python, :p
>
> Puntualmente, acá:
>
>   http://docs.python.org/2/library/subprocess.html#replacing-os-system
>
> ...que lo que hace es usar retcode = call(cmd, shell=True).
>
> Yo no puedo usar .call() porque necesito NO esperar a que termine lo
> que disparo, pero me dio la idea de leer el return code (exit status)
> de shell, lo cual no es trivial, porque hay que esperar un ratito:
>
> Al final, terminé haciendo esto, que funciona "lo suficientemente bien":
>
>         try:
>             p = subprocess.Popen(cmd, shell=True)
>         except OSError, err:
>             self.logger.error("Execution failed: %s", err)
>             widgets.show_error_dialog("Execution failed: " + str(err))
>         else:
>             # wait for the shell to execute and give it time to finish by
>             # error if it had a problem; note that this sleep time does
>             # not affect at all the GUI interaction
>             time.sleep(1)
>
>             # the poll is needed for the returncode to be set
>             p.poll()
>
>             if p.returncode is None or p.returncode == 0:
>                 self.logger.info("Execution ok, pid=%d", p.pid)
>             else:
>                 self.logger.error("Execution failed, child returned %r",
>                                   p.returncode)
>                 widgets.show_error_dialog("Execution failed, child returned " +
>                                           repr(p.returncode))
>
>
> Lo único que me faltaría es "traducir" el exit status de bash a algo
> más humano en los casos en que estén bien definidos.
>

Siguiendo la linea de usar Popen:

import subprocess
import sys

p = subprocess.Popen(["ls", "-l", "/tmp", ], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(output, err) = p.communicate()

if p.returncode != 0:
    print "Oh, oh! Last words were '{}'".format(err)
    sys.exit(1)

print "Houston, we hace a pid {}".format(p.pid)
for lines in output.split('\n'):
    print lines


    Ezequiel



More information about the pyar mailing list