Utilización de Threads en Python con Boa Constructor y wxPython GUI

Visitas: 55  
Tiempo total: 0 días con 12:26:9 hrs  

Esta publicación trata sobre el uso de líneas de tiempo, timer o Threads en Python utilizando Boa Constructor en GNU/Linux.

IDE

im1

BOA constructor
v0.6.1
A Python IDE and wxPython GUI builder

OS

im2
GNU/Linux
Ubuntu 13.04

El código de esta publicación fue utilizado en Ubuntu pues la instalación de Boa Constructor es bastante más fácil utilizando el centro de software en comparación si se utiliza la consola de GNU/Linux en la distribución de Fedora 19.

Plantilla para la utilización de Threads:

import threading 
import wx 

class tiempo(threading.Thread):  
    #Constructor 
    def __init__(self): 
        threading.Thread.__init__(self)  

    #Tiempo 
    def run(self): 
        self.procesar()

    def procesar(self): 
	#código

im3

Para la utilización de este código en cualquier parte de la aplicación, por ejemplo en un Frame y suponiendo que el archivo Python que contiene la clase tiempo mostrado anteriormente es llamado tiempos.py, se utiliza el siguiente código:

from tiempos import tiempo 

...

def __init__(self, parent): 
	self._init_ctrls(parent) 
	# 
	self.tiempo_ = tiempo()
	self.tiempo_.start()

Para el código anterior se debe suponer un Frame del IDE Boa Constructor.

im4

Comunicación entre Threads y wxPython GUI

wxPython GUI es la interfaz utilizada en Boa Constructor, el cual puede contener por ejemplo alguno de los siguientes elementos:

Elemento WxPython GUI
Texto wx.TextCtrl
Etiqueta wx.StaticText
Lista de selección wx.ComboBox
Lista de texto wx.ListBox
Boton wx.Button

Para poder utilizar los elementos de esta GUI en los Threads, es necesario que las clases que implementan el tiempo tengan acceso a una variable que contenga los elementos gráficos, para esto se pasa el contenedor al momento de inicializar la clase:

Frame

self.tiempo_ = tiempo(self)
self.tiempo_.start()

 Thread

def __init__(self,parent):
        self.parent=parent

def procesar(self):
        #self.parent

Al momento de simplemente editar alguno de estos elementos desde algún Thread se generara una serie de errores, alguno de estos son:

Llamada simple desde la clase tiempo que implementa los Threads:

self.parent.txt.Clear()
self.parent.txt.AppendText("Hola mundo")

Suponiendo que el elemento wx.TextCtrl es llamado txt, la aplicación puede tener algunos o todos de los siguientes errores dependiendo del tipo de implementación que se realiza:

(Python:3809): Pango-CRITICAL **: pango_layout_get_text: assertion `PANGO_IS_LAYOUT (layout)' failed

(Python:3830): GLib-GObject-CRITICAL **: g_object_ref: assertion `object->ref_count > 0' failed

(Python:3830): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(Python:3830): LIBDBUSMENU-GLIB-WARNING **: Translation has an invalid value 'I-->D' for default text direction.  Defaulting to left-to-right.

im5

Para solucionar este problema, únicamente se utilizan los métodos: wx.PostEvent, wx.CallAfter and wx.CallLater. Para no mostrar información redundante una de las soluciones para este problema es la siguiente línea de código en la clase que implementa el Thread:

#Tiempo 
def run(self): 
	wx.CallAfter(self.procesar)

En este caso self.procesar es el método que utilizara los elementos GUI de la aplicación.

Implementación de los Threads

Para hacer correr una línea de tiempo, se debe de utilizar la función timer.sleep o bien wx.Sleep, esta última no tiene la precisión en milisegundos que tiene timer.sleep.

Implementación de timer.sleep

import threading, time
import wx

class tiempo(threading.Thread):  
    #Constructor
    def __init__(self,parent):
        self.parent=parent
        Threading.Thread.__init__(self)  

    #Stop
    def stop(self):
        self.i = -10

    #Tiempo
    def run(self): 
        self.i = 1
        while self.i > 0:
            wx.CallAfter(self.procesar)
            time.sleep(0.1)

    def procesar(self):
        #self.parent

Su implementación en un archivo Frame es la siguiente:

self.tiempo_ = tiempo(self)
self.tiempo_.start()

Para detener su funcionamiento:

self.tiempo_.stop()

Referencias

[http://www.blog.Pythonlibrary.org/2010/05/22/wxPython-and-Threads/]
[http://091labs.com/wp-content/uploads/2011/11/python.png]

Posdata

Los Threads se deben de detener y eliminar correctamente para evitar seguir consumiendo los recursos de la PC en dado caso se esté desarrollando alguna aplicación en un nivel mas formal. En esta publicación no se encuentra dicha implementación.


Para recibir boletines de información, por favor escribe tu correo electrónico:

Por favor ingrese un correo electrónico valido.
Registrado correctamente!