Cmd: Creando una consola interactiva con Python

Python

Python

Siguiendo con los ejemplos de los grandes recursos que ofrece la standard library de Python, así como el otro día hablé sobre BaseHTTPServer, hoy voy a hablar de Cmd.

Cmd es un módulo que nos permite crear una consola interactiva, como la propia consola de Python, en unas pocas líneas. La consola incluye manejo de distintos prompts, hooks para la ejecución de comandos, manejo de historial, ayuda general y por comando, y autocompletado de comandos y parámetros, etc. Lo único que tenemos que hacer para implementarla es extender la clase cmd.Cmd e implementar métodos do_* para los distintos comandos que queramos definir.

Veamos las opciones disponibles con un ejemplo muy sencillo:

# -*- coding: utf-8 -*-
import cmd

class Console(cmd.Cmd):

    prompt = "> "

    _colors = {‘red’: ‘#FF0000′,
               ‘white’: ‘#FFFFFF’,
               ‘black’: ‘#000000′}

    def __init__ (self):
        """Constructor"""
        cmd.Cmd.__init__(self)

    def do_hello (self, name):
        """Says hello to someone"""
        print "Hello %s!" % name

    def do_get_color (self, color):
        """Prints out the hex representation of a color"""
        if color in self._colors:
            print "%s: %s" % (color, self._colors[color])
        else:
            print "I don’t know: %s" % color

    def complete_get_color (self, text, line, begidx, endix):
        """Complete function for get_color"""
        return [i for i in self._colors if i.startswith(text)]

    def do_quit (self, s):
        print "Bye, bye…"
        return True

    def help_quit (self):
        print "Quits the console"

    do_EOF = do_quit
    help_EOF = help_quit

if __name__ == "__main__":
    console = Console()
    try:
        console.cmdloop("Hola!")
    except KeyboardInterrupt:
        console.do_quit(None)
 

Inicialización

Lo primero que hacemos es definir la clase Console que extiende cmd.Cmd. Luego definimos la propiedad pública “prompt”, que será el prompt de la consola (por default “(Cmd)”).

Un método básico

Luego tenemos el método do_hello que toma un argumento y le dice hola al argumento. Notesé que el texto que definimos en el comentario (“Says hello to someone”), además de ser la documentación de la función es tomada por Cmd para mostrarlo como ayuda del comando. Si en la consola ponemos “? hello” o “help hello”, se imprimirá esa cadena.

Autocompletado

A continuación tenemos el método do_get_colors que imprime el código hexadecimal de un color, según el diccionario _colors. Además de tener su texto de ayuda, a continuación tenemos el método complete_get_colors que lo que hace es manejar el autocompletado de los parámetros. Aquí lo que hacemos es ver el texto que se tipeó y devolver todas las claves del diccionario _colors que empiecen con ese texto.

Salir de la consola

Para salir del loop de la consola un método tiene que devolver True. Para ello definimos el método do_quit. Aquí imprimimos un saludo y salimos. Las novedades son, por un lado, la función help_quit que cumple la misma función que el docstring: imprime la ayuda del comando quit. Y además duplicamos la función do_quit como do_EOF (y help_quit como help_EOF). De esta forma, cuando la consola reciba EOF (es decir, Ctrl+D) ejecutará do_quit y saldrá.

Ejecutando la consola

Por último, al final del código instanciamos la clase Console y ejecutamos el método cmdloop() que inicia el loop de la consola. De paso agregamos el handling de la excepción KeyboardInterrupt (es decir, Ctrl+C) para que ejecute do_quit y cierre la consola adecuadamente.

Otro ejemplo

Así como hice la última vez, les dejo otro ejemplo más completo en el que anduve trabajando. En este caso es parte del código de mi modesto proyecto python-directadmin. Se trata de DAConsole, una pequeña consola interactiva para interactuar con Directadmin, donde implemento todas estas cosas vistas aquí, además de la posibilidad de crear consolas anidadas.

Ver código de DAConsole.

Referencias

Probando nuevo diseño: zBench

Me dieron ganas de probar un nuevo diseño para el blog, un poco más legible. Después de bastante tiempo usando themes negros, esta vez elegí uno más claro, con un mejor contraste que facilite la lectura.

Encontré zBench que me pareció que cumplía con los requisitos que buscaba. Además es un theme muy completo, que implementa la mayor parte de las funcionalidades de WordPress, define estilos para <pre> y <blockquote> que acá uso bastante y me parece lindo.

Así que me tomé algunos minutos para traducirlo (algo que no había hecho con themes anteriores) y lo dejé andando. De paso también vi que el código es bastante prolijo, lo cual es otro punto a favor.

¿Qué les parece?

Pegá el folleto de las Charlas de Python en tu lugar de trabajo!

Como les contaba hace unos días, el 24 de julio empieza el Ciclo de Charlas Abiertas de Python Argentina en la sede del Colectivo La Tribu, Lambaré 873.

Charlas Abiertas de Python el La Tribu

La entrada es libre y gratuita. Se pasará una gorra voluntaria durante los cursos para hacer frente a viáticos y gastos generales.
No hace falta registrarse, pero vengan temprano para asegurarse un lugar porque los cupos son limitados.

La gente de PyAr está invitando a pegar el folleto de las charlas en facultades y lugares de trabajo.

Mapa:


View Larger Map

Python BaseHTTPServer: un servidor HTTP en unas pocas líneas

Python

Python

Python es un lenguaje tan poderoso que me sorprende constantemente. Particularmente su librería standard incluye tantas cosas maravillosas que lleva tiempo ir descubriéndolas todas.

Hoy voy a hablar de BaseHTTPServer un módulo de Python 2.x (en 3.x se llama http.server) que nos permite implementar un servidor web en muy pocas líneas de código. Es la base de otros dos módulos muy interesantes, SimpleHTTPServer y CGIHTTPServer. El primero implementa un muy simple servidor web que sirve archivos y el segundo es un servidor que ejecuta script CGI en entornos Unix.

Por ejemplo, con SimpleHTTPServer podemos hacer algo tan maravilloso como esto:

$ cd ~/musica
$ python -m SimpleHTTPServer

Y con sólo eso tenemos montado un servidor web escuchando en 0.0.0.0:8000 y sirviendo todos nuestros archivos de la carpeta ~/musica.

Pero la clase BaseHTTPServer es más poderosa porque nos permite implementar nuestros propios RequestHandlers, es decir, clases que extiendan BaseHTTPRequestHandler y hagan lo que nosotros queramos en cada petición para cada método HTTP. Por ejemplo, para implementar el método GET solamente hace falta crear una clase que extienda BaseHTTPRequestHandler y sobrecargar el método do_GET.

Por ejemplo, si yo quisiera implementar un muy básico servidor que me diga el load average del sistema sería tan sencillo como poner:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import BaseHTTPServer

class RequestHandler (BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET (self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(self._get_status())
        return
    def _get_status (self):
        return "Status:\n" \
               "——-\n" \
               "Load average: %s\n" % \
               ("%01.2f, %01.2f, %01.2f" % \
                           os.getloadavg())            

def main (args):
    httpd = BaseHTTPServer.HTTPServer((‘localhost’, 8000), RequestHandler)
    httpd.serve_forever()

if __name__ == "__main__":
    sys.exit(main(sys.argv))
 

Y al entrar a http://localhost:8000 vería algo así:

Status:
-------
Load average: 0.26, 0.35, 0.40

A esta altura creo que se hace bastante evidente el potencial de esta clase BaseHTTPServer. Piensen lo sencillo que sería hacer un servidor para un web service REST (RESTful web service) implementando métodos do_GET, do_DELETE, do_POST etc.

Para jugar un poco hice una versión un poco más completa de este servidor de status. Al correrlo lanza el servidor HTTP, al cual podemos acceder para pedirle un status general del sistema en tres formatos: texto plano (plain), HTML y JSON. También le agregué un OptionParser para poder configurar el host y puerto en el cual el servidor deberá escuchar. Con comentarios y todo ocupa 149 líneas.

Pueden ver el código aquí: http://pastebin.com/G5FgTDiv

Ciclo de Charlas Abiertas de Python Argentina en La Tribu

Python Argentina

Python Argentina

PyAr,  la comunidad de Python Argentina presenta el Ciclo de Charlas Abiertas de Python 2010 en la sede del Colectivo La Tribu.

Se trata de una serie de presentaciones que tendrán lugar los días sábados, a lo largo de la segunda mitad del año, desarrollando distintos temas relacionados con Python desde los más básicos a algunos bastante avanzados. Las charlas estarán a cargo de miembros de la comunidad PyAr, destacados desarrolladores con un profundo dominio del lenguaje en cuestión.

Las charlas comienzan el sábado 24 de julio, su entrada es libre y gratuita (sin necesidad de registrarse) y tendrán lugar en la sede del Colectivo La Tribu, sito en Lambaré 873, Capital Federal [ver mapa].

A continuación una versión resumida del cronograma de charlas. La versión completa con descripciones y horarios pueden consultarla en la página de PyAr.

Cronograma

Día 1: Sábado 24 de Julio
Tema: Introducción a la Programación
Disertante: Facundo Batista

Día 2: Sábado 31 de Julio
Tema: Introducción a Python
Disertantes: Tomás Zulberti y Facundo Batista

Día 3: Sábado 21 de Agosto
Tema: Introducción al Desarrollo Web I
Disertantes: Mariano Reingart y Alejandro J. Cura
Tema: FooBar (virtualenv, buildout, nose)
Disertante: Roberto Alsina

Día 4: Sábado 11 de Septiembre
Tema: Introducción al Desarrollo Web II
Disertantes: Mariano Reingart y Alejandro J. Cura
Tema: Django
Disertante: Manuel Kauffman

Día 5: Sábado 25 de Septiembre
Tema: Introducción a las Interfaces Gráficas de Escritorio I
Disertante: Roberto Alsina
Tema: Plone
Disertante: Roberto Allende

Día 6: Sábado 2 de Octubre
Tema: Introducción a las Interfaces Gráficas de Escritorio II
Disertante: Roberto Alsina
Tema: wxPython
Disertante: Mariano Reingart

Día 7: Sábado 30 de Octubre
Tema: Optimizando Python
Disertante: Gabriel Genellina
Tema: PyQt
Disertante: Roberto Alsina

Día 8: Sábado 13 de Noviembre
Tema: Python 3000
Disertante: Facundo Batista
Tema: Twisted
Disertante: Lucio Torre

Día 9: Sábado 27 de Noviembre

Tema: Taller de Programación de Juegos
Disertantes: Alejandro J. Cura y Hector Sanchez