Posteado por: Daniel Fuentes en: Mayo 21, 2009
Uno de los problemas que se producen al crear aplicaciones en pygtk es que si se ejecuta algún comando externo o dentro del mismo código algo que se demore su tiempo en ser ejecutado, mientras se lleva a cabo esta tarea la ventana literalmente se congela/bloquea hasta que se termina de realizar esta tarea, además que no muestra el resultado hasta que termina (y en muchos casos uno quiere mostrar el progreso mientras se ejecuta la tarea)
Una de las soluciones a esto es usar threads (hilos), pero NO “de la manera normal” como es usan, ya que si se hace de forma normal, los widgets no se comportan siempre como es debido y a veces los threads ni siquiera funcionan.
La solución es usar los métodos gtk.gdk.threads_init(), gtk.gdk.threads_enter() y gtk.gdk.threads_leave() de la siguiente forma:
Ahora veamos el ejemplo (con los correspondientes comentarios), mas adelante lo explico con mas detalles:
#!/usr/bin/env python
import pygtk
pygtk.require("2.0")
import gtk
import os
import threading
# iniciamos los thead (los iniciamos, aun no lo usamos)
gtk.gdk.threads_init()
comando = "find /var"
# Esta funcion hace el trabajo "pesado", luego es llamada desde la ventana
def salida_comando(salida_texto, buffer_texto, comando):
output = os.popen(comando)
while True:
linea = output.readline()
if not linea:
break
# Comienza el trababjo pesado, asi que entramos en un thread
gtk.gdk.threads_enter()
# Se inserta la siguiente linea de la salida del proceso y luego se
# coloca el cursor al final del textview (se mueve el scroll)
iter = buffer_texto.get_end_iter()
buffer_texto.place_cursor(iter)
buffer_texto.insert(iter, linea)
salida_texto.scroll_to_mark(buffer_texto.get_insert(), 0.1)
# Finaliza el trabajo pesado, asi que salimos del thread
gtk.gdk.threads_leave()
# Clase con la ventana principal.
class MainWindow:
def __init__(self):
# Definimos la ventana inicial
ventana = gtk.Window(gtk.WINDOW_TOPLEVEL)
ventana.set_title("Ejemplo de threading en gtk")
ventana.resize(450,300)
ventana.connect("destroy", gtk.main_quit)
# Creamos una caja vertical con un espacio entre widgets de 5px y con
# la propiedad homogeneo en False. Luego agragamos las widgets al vbox
vbox = gtk.VBox(False, 5)
# Una simple etiqueta que se muestra en la parte superior de la ventana
etiqueta = gtk.Label("Resultado del comando:")
# Creamos un textview que tenga un auto scroll, o sea que se desplace
# solo al aparecer nuevo texto que sobrepase la pantalla
# en este textview se mostrara la salida del comando ejecutado
scrollwin = gtk.ScrolledWindow()
scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
salida_texto = gtk.TextView()
buffer_texto = salida_texto.get_buffer()
scrollwin.add(salida_texto)
# creamos un boton, el que iniciara el comando al hacer click en el
boton = gtk.Button("iniciar programa")
boton.connect("clicked", self.on_boton_clicked, salida_texto, buffer_texto, comando)
# Empacamos el textview con scroll y el boton dentro del vbox
vbox.pack_start(etiqueta, False, False, 0)
vbox.pack_start(scrollwin)
vbox.pack_start(boton, False)
# y luego unimos el vbox la ventana pricipal y la mostramos
ventana.add(vbox)
ventana.show_all()
def on_boton_clicked(self, widget, salida_texto, buffer_texto, comando):
# Este boton es el lanza el hilo (threading) al hacer click sobre el
hilo = threading.Thread(target=salida_comando, args=(salida_texto, buffer_texto, comando))
hilo.start()
if __name__ == "__main__":
MainWindow()
gtk.main()
Lo que hace el programa es ejecutar un comando “find /var” y luego muestra la salida de este en la ventana
La clase MainWindow crea la ventana de pygtk, es muy parecida al primer ejemplo que vimos en el tutorial de introducción a pygtk, el único detalle es que al hacer click en el boton (on_boton_clicked) se inicia un thread (hilo) que ejecuta la función salida_comando con los correspondientes argumentos.
En cuanto a la salida_comando es una función que ejecuta un comando (usando os.popen) tal como si uno lo escribiera en un terminal y luego toma el texto que resulta de ejecutar el comando y lo muestra en el textview de nuestra ventana. Esta funcion contiene la parte del código que hace el trabajo pesado, por esto tiene los gtk.gdk.threads_enter() y gtk.gdk.threads_leave()
Y así se ve la ventana funcionando:

Claro que esta no es la única forma de hacerlo, o sino miren en las faqs de pygtk
Posteado por: Daniel Fuentes en: Mayo 2, 2009
Eso es exactamente, un generador de contraseñas aleatorias, rápido y bonito, obviamente hoy hay nada de criptografía en este, solo se escogen valores al azar obtenidos desde una cadena para formar una contraseña (como las típicas que te asignan al registrarse en algun sitio)
#!/usr/bin/env python from random import choice longitud = 18 valores = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<=>@#%&+" p = "" p = p.join([choice(valores) for i in range(longitud)]) print p
bastante simple, en longitud se le indica la longitud de la contraseña (en este caso 18 letras) y en valores son las posibles letras con las que se formaran la contraseña (allí cada uno escoge ).
Nota: puede ser recomendable omitir el 1,l,O,0 porque a veces se confunden y omitir algunas letras para que por azar no se creen palabras ofensivas.
Posteado por: Daniel Fuentes en: Abril 25, 2009
Otro de mis tutoriales, esta ves se trata de como crear un paquete Debian a partir de algún script/programa escrito en python. Por que escribo esto, es simple es que he visto por allí formas no muy correctas de hacerlo (si crean el paquete pero si lo revisan con lintian o similares, este tiene muchos errores)
Como es casi costumbre vamos a empaquetar el ejemplo del conversor de temperatura.
Necesitamos:
Además tenemos que tener claro que el nombre de un paquete debian es de la forma:
<nombre_del_paquete>_<numero_de_version>-<numero_de_revision_debian>.deb
A continuación los pasos a seguir:
Leer el resto de esta entrada »
Posteado por: Daniel Fuentes en: Marzo 15, 2009
En este tercer tutorial de pyGtk/Glade, voy a explicar como traducir (o internacionalizar) el texto de los mensajes, etiquetas, botones, etc. de tal manera que se muestren en el idioma predeterminado del sistema. Para ello voy a utilizar el ejemplo del segundo tutorial (que es el anterior a este):
En donde al pequeño programa (pytemp) lo voy a traducir al español. Para ello primero hay que marcar que cadenas se van a traducir dentro del código y en el archivo glade, para después poder generar los archivos de la traducción
Leer el resto de esta entrada »
Posteado por: Daniel Fuentes en: Febrero 16, 2009
En el siguiente tutorial voy a explicar como crear una aplicación simple usando pygtk y glade, la aplicación que voy a crear es un programa que convierte unidades de temperatura (por ejemplo pasa de Celsius a Fahrenheit o Kelvin), claro que no es un gran programa pero es mucho mejor que el “hola mundo” que hice para el primer tutorial, la introducción a pygtk+glade .
En cuanto al nombre del programa, lo voy a llamar “python temperature converter” (pytemp para abreviar). Así que sin mas preámbulo pasemos al tutorial
Leer el resto de esta entrada »
Posteado por: Daniel Fuentes en: Febrero 10, 2009
Mientras miraba un poco un ejemplo, vi que se usaba el comando yield en un par de oportunidades (que se usan para crear generadores). Básicamente los generadores se escriben funciones normales, pero usan la sentencia yield en vez de un return dentro de un bucle. Yield funciona de manera similar al return, pero la gracia de usar el yield es que conserva la iteración del bucle para la siguiente vez que se le invoque, esto queda mas claro con un ejemplo, así que abrimos el interprete en modo interactivo para hacer el siguiente ejemplo:
>>> def contador(max): ... n=0 ... while n < max: ... yield n ... n +=1 ... >>> gen=counter(3) >>> gen.next() 0 >>> gen.next() 1 >>> gen.next() 2 >>> gen.next() 3 >>> gen.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration >>>
Al invocar el “contador” que definimos, este devuelve un objeto de tipo Generator. Este objeto tiene el método next() que permite ir obteniendo valores del bucle cuando se necesitan y cuando los generadores terminan su ejecución, hacen saltar la excepción StopIteration automáticamente.
Además, podemos hacer varias cosas, como por ejemplo usar el yield dentro de un bucle infinito (en el siguiente ejemplo seria el while True) de esta manera cuando termina de iterar vuelve a empezar. En este caso voy a hacer que recorra los elementos de un lista
>>> def recorre(list): ... while True: ... for n in list: ... yield n ... >>> gen=recorre([1, "a", 2, "hola"]) >>> gen.next() 1 >>> gen.next() 'a' >>> gen.next() 2 >>> gen.next() 'hola' >>> gen.next() 1 >>> gen.next() 'a' >>>
Y podríamos continuar así de manera indefinida (evidentemente la lista puede contener cualquier cosa). La utilidad de esto es que se pueden usar iterables fuera de un bucle de una manera sencilla.
Posteado por: Daniel Fuentes en: Febrero 5, 2009
De vuelta de mis vacaciones, con las pilas recargadas, se me ha ocurrido escribir un pequeño tutoríal de introducción a la creación de interfaces gráficas usando python, GTK+ y glade. El cual dejo a continuación.
El tutoríal esta dividido en dos partes, en cada parte se explica como crear una ventana que tiene un texto (una etiqueta de texto para ser exactos), un cuadro donde escribir y un botón. La idea es que al escribir un texto en la entrada de texto (el cuadro), y al presionar el botón OK (o la tecla ENTER) el texto se muestra en la etiqueta de la forma “Hola **nuestro_texto**”. No es un gran programa pero sirve de ejemplo.
En la primer parte explica como crear el ejemplo directamente sobre el código, o sea construir la interfaz y conectarla directamente, todo esto desde el mismo archivo en python, o sea todo hecho a mano. Mientras que en la segunda parte se explica como crear la interfaz desde el diseñador de interfaces Glade (de forma separada y bastante intuitiva) y luego conectarla (llamarla) desde el archivo en python.
Pero antes de empezar, hay que instalar pygtk y el soporte para glade, desde debian (y derivadas como ubuntu) es tan fácil como hacer un:
apt-get install python-gtk2 python-glade2
Además para la segunda parte se necesita glade para crear la interfaz gráfica (Aunque no es necesario para ejecutarla), así que hacemos:
apt-get install glade
Ahora manos a la obra
Leer el resto de esta entrada »
Posteado por: Daniel Fuentes en: Septiembre 10, 2008
Otra de las entradas de mi antiguo blog (batibit), esta vez se trata de una explicación para traducir aplicaciones (crear aplicaciones multilingües) en python
Necesitamos:
La Explicación:
Primero hay que tener un programa que vamos a traducir, para el ejemplo voy a usar el simple y clásico:
print ("Hello")
Luego hay que modificar un poco el programa para indicarle que textos se deben traducir, esto se hace al importar el modulo gettext en python, lo que dejaría el programa como el que sigue:
import gettext
gettext.textdomain("programita")
gettext.bindtextdomain("programita", "/mo")
print gettext.gettext("Hello")
Esto parece complicado, pero no lo es, lo que se hizo es lo siguiente:
Se uso las funciones “textdomain” y “bindtextdomain” para indicarle donde se encuentran las traducciones del programa (y el nombre de este). En este caso como es un ejemplo tienen que cambiar “programita” por el nombre del programa que se esta traduciendo, y “/mo” por el directorio donde van a estar las traducciones.
Posteado por: Daniel Fuentes en: Septiembre 8, 2008
Esto es algo que había publicado en mi antiguo blog (ya desaparecido), asi que lo vuelvo a poner en caso de que a alguien le interese.
Se trata de que se puede usar dbus para mostrar una notificación en nuestro escritorio (por lo menos en gnome, donde lo probé), como la que muestro en la siguiente captura:

El código es el siguiente (es bastante simple y con los comentarios que tiene queda explicado por si solo)
#!/usr/bin/env python
import dbus
# Inicializando el bus de tipo session (se comunica entre aplicaciones)
bus = dbus.SessionBus()
# Se obtiene el objeto Notifications (es el encargado de las notificaciones)
notify_object = bus.get_object('org.freedesktop.Notifications','/org/freedesktop/Notifications')
# Se obtiene una interface del tipo Notificatios
notify_interface = dbus.Interface(notify_object,'org.freedesktop.Notifications')
# Finalmente lanzamos la notificacion
# Nota: el gtk-ok muestra un icono de ok en el mensaje, puede ser cualquier otro
# como gtk-cut (muestra una tijera), gtk-connect (una conexion), etc.
notify_id = notify_interface.Notify("DBus Test", 0, "gtk-ok", "Hola a todos",'Un ejemplo de mensaje o texto a mostrar', "",{},10000)
# Imprimimos el ID de esta notificacion
print "El ID de la notificacion es: ", notify_id
Posteado por: Daniel Fuentes en: Septiembre 8, 2008
Otro blog mas que inicio (y espero que no caiga en el olvido como los demás), en este caso voy a dejar aquí todas esas cosas que he aprendido mientras uso python, algo así como un archivo de apuntes y de paso si le sirven a alguien sería bueno.