.
     
» Ajax Links          

pygtk threads subprocess

6 Nov 2009 | Escrito por: lopz | En: Python
pygtk threads subprocess commands

Hola

Después de mucho tiempo sin escribir nada paso a poner una breve nota sobre el uso de threads en pygtk, en google hay mucha información al respecto, inclusive en su página hay esto:
http://faq.pygtk.org/index.py?file=faq20.006.htp&req=show

Y bueno, escribí un pequeño trozo de código que será fácil entender si se lee el anterior link, en esta ocasión pasaré de escribir línea a línea el script xD


Code:
import gtk
import os
import subprocess as sp
import time
import threading

gtk.gdk.threads_init()
#gobject.threads_init()

CMD = 'du -sh /home/lopz/'

class MainWin:
    """
    Creates a main window object
    """
    def __init__(self):
   w = gtk.Window()
   self.pb = gtk.ProgressBar()
   box = gtk.HBox(False, 0)
   self.btn_start = gtk.Button("Start")
   self.btn_start.connect("clicked", self.btn_start_click)
   box.pack_start(self.btn_start)
   btn_test = gtk.Button("Test")
   btn_test.connect("clicked", self.btn_test_click)
   box.pack_end(btn_test)

   self.btn_stop = gtk.Button("Stop")
   self.btn_stop.connect("clicked", self.btn_stop_click)
        self.btn_stop.set_sensitive(False)
   box.pack_end(self.btn_stop)

   box.pack_start(self.pb)

   w.add(box)
   w.show_all()
   w.connect("destroy", self.quit)

    def get_popen(self, cmd):
        return sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.STDOUT)
   
    def pulse(self):
   while not self.quit:
       time.sleep(0.1)
       gtk.gdk.threads_enter()
       self.pb.pulse()
       gtk.gdk.threads_leave()

    def exec_cmd(self):
   self.popen = self.get_popen(CMD.split())
   out = self.popen.stdout.read()
        if out:
            print out
            self.terminate()
       
    def terminate(self):
   self.quit = True
   os.kill(self.popen.pid, 9)
        self.btn_stop.set_sensitive(False)
        self.btn_start.set_sensitive(True)
        print "Terminate threads"

    def quit(self, widget):
   gtk.main_quit()
   self.terminate()

    def btn_test_click(self, widget):
   print "gtkMain thread"

    def btn_stop_click(self, widget):
   self.pb.set_text("Completed")
   self.terminate()

    def new_thread(self, method):
        t = threading.Thread(target=method, args=())
   t.start()


    def btn_start_click(self, widget):
   print "Start threads"
        self.quit = False
        self.btn_stop.set_sensitive(True)
        widget.set_sensitive(False)
        self.pb.set_text('Running')
        self.new_thread(self.pulse)
        self.new_thread(self.exec_cmd)
       
if __name__ == "__main__":
    gui = MainWin()
    gtk.gdk.threads_enter()
    gtk.main()
    gtk.gdk.threads_leave()


A grandes rasgos lo que hace el script es lo siguiente:

crea una ventana con unos 3 widgets dentro, un progressbar y 3 botones, el progressbar es para mostrar al usuario que aún se está realizando la tarea, el botón start pues empieza la tarea, el stop detiene todo y el test lo que hace simplemente es imprimir en consola.
Start: Lanzará 2 threads, en uno lo que hacemos es modificar los widgets, ahí puedes modificar cualquier parte de la interfaz mientras estás haciendo alguna tarea junto a este threads lanza otro donde se ejecutará nuestra tarea pesada, en este caso el comando du -sh /home/tu_user que lo que hace es mostrar el tamaño del directorio, como este comando tiende a tardar en mostrar el resultado al usuario le mostraremos una barra de progreso para que sea que aún se está realizando la tarea.
stop: lo que hace es terminar ambos hilos, el que muestra la barra de progreso y el que ejecuta el comando, en este caso matando el pid del comando y automáticamente sale del hilo.
test: este botón es una prueba que podemos usar nustra gui mientras ejecutamos tareas pesadas por debajo, y este solo imprime en consola desde el thread de main.

El botón salir de la ventana hace lo mismo que el botón Stop, para ambos threads y luego destruye la ventana del hilo principal, si no destruimos los hilos uno quedará pegado hasta que termine de ejecutarse nuestro comando, cosa que no queremos.

Creo que es todo, para ser un pequeño ejemplo para ayudar a un amigo va bien y de paso recordé un poco esto de python que lo tengo ya olvidado.

A continuación pasaré como siempre a pegar una pequeña captura de pantalla de la pequeña gui funcionando.



Espero que a alguien le sirva y deja algún comentario.

Igual se puede usar gobject.idle_add(mi_funcion) pero esto no toqué para nada.
tampoco he visto cual sea la manera correcta o la mejor de hacerlo.

Tu amigo programador de python+pygtk ¿Cómo solucionas este tipo de problemas?

Saludos!


   

 
tabris17 Ene 2010
Interesante como para practicar un poco

lopz7 Nov 2009
Hola

Pues si, es solamente para un ejemplo el comando que puse, pero tampoco se si estará bien o sea lo correcto hehe

shakaran7 Nov 2009
Me parece que para ver el tamaño del directorio puedes usar funciones de PyGTK (si realmente quieres hacer eso y no es para un ejemplo).

Sino, esta bastante bien el script ;)

  Pagina 1 de 1
 

Envia tu Comentario:
Los comentarios ofensivos o fuera de lugar seran borrados.
BBcode: on
Smilies: on
Nick:


smile wink surprised tongue lol sad angry cry 



Status: Comentario aun no enviado


Powered by MySql' Powered by PHP XHTML Valido CSS Valido

Tiempo de carga del servidor: 0.1248