jueves, abril 10, 2008

Pares clave-valor persistentes

Para almacenar persistentemente pares clave-valor disponemos de GDBM - The GNU database manager. La cual es la reimplementacion de dbm para gnu.
Como no podia ser de otra manera tenemos un módulo en python para hacer uso de ella.

Otra implementacion es bdb.

Como otros almacenamientos persistentes tenemos:

Mondrian Code Review On The Web


Creo que fue en el video sobre Google App Engine, donde escuché sobre Mondrian.
Aprovechando que ahora tengo tiempo lo he estado viendo... y merece la pena verlo.

La charla, impartida por Guido, empieza mostrando lo que usaban antes de que implementaran Mondrian, lo que aporta Mondrian y sus ventajas. Básicamente usaban varios scripts.
Ah! antes de nada comenta sobre la filosofía de trabajo. Parte de él es hacer reviews del código fuente.

Hacer revisiones es una alternativa a la xp. Eso si con el mismo objetivo, mejorar la calidad. ¿Donde he visto yo estas practicas? ¿En ningún sitio?

Gracias al video me enterado de cosillas, como por ejemplo que prácticamente no usan branches, y que como sistema de control de versiones usan Perforce [wikipedia][site].

Lo que hace en pocas palabras
Lo que tienen ahora es una aplicación web que gestiona todo el tema de las reviews.
Como desarrollador te revisan y revisas. En la pantalla puedes ver en 2 paneles codigo antiguo y nuevo, poner comentarios....
Ademas se hace uso del correo para enviar notificaciones, ...
Todas estas cosillas siempre se guardan, usandose para ello BigTable+GFS.
Lógicamente también tienen que acceder al servidores de Perforce, y a los entornos de los usuarios (soportan SSH y NFS).

Como lo hacen
Guido comenta que casi podría correr en una maquina, ya que casi todo el trabajo pesado se hace fuera (Perforce, GFS, rendering de html), pero que lo tienen montado en dos maquinas: una para el mail server y otra para el web server.

Y como no podría ser de otra manera usan python a saco: el mail server es wsgiref (multithread y estandard) y el mail server smtpd.py (monothread).

El interfaz es html+css, usando las templates de django, y como no podía ser de otra manera, usan AJAX.

Para hacer los diffs usan la librería de python difflib.

Tanto smtpd, como wsgiref y difflib son módulos estándares de la distribución de python.

miércoles, abril 09, 2008

Visual Test


Hablando ayer con mi futura cuñaaaaaaaa, le comentaba que hace años mil yo usaba Visual Test para la automaticación de pruebas de interfaces graficas.

El motivo de la conversación era porque estabamos generando .avi's a parter de dvds. El problema de dejar lanzado un lote de generaciones es que si te sale un popup, por algun problema o alerta, el proceso se para (usamos autogk). Le comenté que eso se podría solventar con un script realizado con visual test, y de ahí este dejavú.

La verdad es que era supercomodo de usar. Te grababas las accciones y automáticamente se generaba un script. Script que luego podrias adaptar.
Con N de estos scripts te montabas ya una batería de pruebas. Era la caña...

Me he quedao sorprendido de, ya no sólo que pasara a ser de Rational, sino que Rational ha pasado a ser de IBM.

Esta es la lista de los productos de rational.
Y como no, el sucesor de visual test está: IBM Rational Robot.

Referencias:
Actualización
  • Para la automatización en unix, disponemos de expect.
  • Como no podia ser de otra manera hay un flavour en python: pexpect.
  • Y una par de herramientas for free para windows: autohotkey y autoit.

martes, abril 08, 2008

Google App Engine

He flipado un poco cuando lo he visto en barrapunto. Esto puede ser un buen empujón para python y django.

Este artículo lo cuenta muy clarito.
Y os recomiendo ver los videos en youtube del Campfire One: Google App Engine.

De momento su uso está cerrado, pero puedes indicar que te avisen cuando vuelvan a ofrecer el servicio. De momento para probar y enredar se puede usar el SDK en local.

La idea de todo esto, es desarrollar y olvidarte del manteniento de la aplicación online, de cuanta maquina necesitas, cuanto espacio en disco, el que este online 24x7,.... Google se ocupa de todo esto.
¿Interesante verdad?
Bueno... la chicha:
Relacionado:
  • Big Table.
  • AWS: "AWS offers into a singular package: storage like S3, auto-scaling and processing power like EC2, and a datastore like SimpleDB." (Simple db: BD hecha en java).

jueves, abril 03, 2008

Python IDEs

Jonathan Ellis comenta que a raiz de un post en un blog ha estado organizando el listado de los editores python 'reales' existentes.
También hay un listado de editores que tienen algún soporte para python, pero que no pueden ser considerados editores 'reales'.

La diferencia entre los primeros y los segundos está principalmente en las facilidades que te den para hacer introspección, depuración y ayuda a la codificación.

martes, marzo 18, 2008

RAID for dummies

Bueno... tras leer sobre RAID (debido al NAS que me he pillado) ahí van unas notas breves:
  • Del RAID 2 y 3 nos podemos olvidar.
  • RAID 0. Los datos se reparten en varios discos. Acceso más rapido tanto en lectura como escritura. No hay redundancia.
    • JBOD: No es realmente RAID 0, pero es parecido. Sirve para ver varios discos como uno solo.
  • Con RAID 1 (data mirroing) tenemos un disco espejo. Con lo cual es la redundancia más cara. No ganamos velocidad en lectura pero si en escritura (normalmente).
  • RAID 4: división por bloques on un disco dedicado a la paridad.
  • RAID 5: se usa mucho, porque se obtiene redundancia a bajo coste. Es mas lento en escritura, ya que hay que calcular los bloques de paridad, que se van escribiendo (es importante estudiar el tipo de acceso de escritura para saber si nos va a liminar). Son necesarios 3 discos. Puede recuperarse ante el fallo de un disco. Pero no ya de un fallo de un segundo disco.
Estos son los clásicos. Pero hay mas:
  • RAID 6: protege ante fallo de dos discos.
  • RAID 5E y 6E
  • RAIDs anidados.
  • .../...

miércoles, marzo 05, 2008

Compartiendo un fichero entre procesos

Imaginaros que se os da la situación en la cual necesitais compartir un archivo entre procesos.
Vamos a ver que opciones tenemos:

[1] Usar como lock un archivo que creamos. Se puede usar la llamada os.open() para crear un archivo en exclusiva. El proceso que lo pueda crear tiene via libre para usar ya el fichero que nos interesa. Hay que tener cuidado con proporcionar los mecanismos para no dejar el lock por ahí.

[2] Usar los mecanismos que nos proporciona el OS para bloquear ficheros. Llamada fcntl.lockf().

A continuación voy a copiar dos scripts que demuestran su uso. Ejecutar en primer lugar uno.py e inmediatamente dos.py en otro terminal.
En estos scripts se hace un open() se bloquea el archivo y despues un close().
Una alternativa seria el tener siempre el open() hecho y simplemente hacer el lockf(). Supongo que esto funcionaría pero no lo he probado.

Ya para acabar, comentar la importancia de hacer el seek() en el segundo script para poder escribir en lugar adecaudo del fichero.

uno.py

import os
import fcntl
import time

#--- Creamos el fichero
h = open("kk.txt","w")
h.write("hello\n")
h.close()

#--- Ahora lo abrimos bloquendolo

h = open("kk.txt","a")
fcntl.lockf(h.fileno(),fcntl.LOCK_EX)
print "Hemos pillado el lock y n os vamos a dormir"
time.sleep(15)
print "escribimos"
h.write("hello\n")
print "Tam: ", h.tell()
#h.flush() -> He procado sin el flush y funciona correctamente,
# pero con el, podría ser mas seguro.
# Adicionalmente está la llamada os.fsync().
# Si queremos mas control en el modo de apertura de los
# ficheros tenemos que usar la llamada os.open().
# Por ejemplo si los queremos crear en exclusiva.
print "Liberamos el lock y cerramos"
fcntl.lockf(h.fileno(),fcntl.LOCK_UN)
h.close()

dos.py

import os
import fcntl
import time



#--- Abrimos
#
# Nota: Si usamos LOCK_NB en lockf al adquirirlo y no podemos,
# nos da un error.

h = open("kk.txt","a")
#fcntl.lockf(h.fileno(),fcntl.LOCK_EX|fcntl.LOCK_NB)
fcntl.lockf(h.fileno(),fcntl.LOCK_EX)
print "Hemos pillado el lock y n os vamos a dormir"

#--- Lo usamos
h.seek(0,2)
print "Tam: ", h.tell()

#--- Cerramos

print "Liberamos el lock y cerramos"
fcntl.lockf(h.fileno(),fcntl.LOCK_UN)
h.close()

lunes, febrero 25, 2008

urllib vs urllib2

Haciendo unas pruebecillas con la página de la wikipedia de mi signo chino, me pasaba una cosa curiosa que era que en la maquina en la que estaba ejecutando mi código me daba un error:


>>> import urllib2
>>> urllib2.urlopen("http://es.wikipedia.org/wiki/Rata")
Traceback (most recent call last):
File "", line 1, in ?
File "/usr/lib/python2.4/urllib2.py", line 130, in urlopen
return _opener.open(url, data)
File "/usr/lib/python2.4/urllib2.py", line 364, in open
response = meth(req, response)
File "/usr/lib/python2.4/urllib2.py", line 471, in http_response
response = self.parent.error(
File "/usr/lib/python2.4/urllib2.py", line 402, in error
return self._call_chain(*args)
File "/usr/lib/python2.4/urllib2.py", line 337, in _call_chain
result = func(*args)
File "/usr/lib/python2.4/urllib2.py", line 480, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden



Pero sin embargo, haciendo un wget, si que la obtenía...
Se me ocurre probar con urllib en lugar de con urllib2 y si que la obtengo. ¿Mande?

Solución ñapa temporal :pppp:


try:
h = urllib2.urlopen(theUrl)
except:
h = urllib.urlopen(theUrl)


¡Dios! ¡soy un lumbreras!
Bueno seamos serios.... tras probar mis cosillas gracias a la ñapa, procedamos a mirar que es lo que realmente está pasando...
Pues lo que está pasando es que urllib2 está enviando unos headers al servidor web que no le molan...
La solución es cambiar el user agent.
Para ello lo que tenemos que hacer es proceder del siguiente modo (por ejemplo):


userAgent = 'Mozilla' # Por ejemplo
headers = { 'User-Agent' : userAgent }
req = urllib2.Request(theUrl, None, headers)
response = urllib2.urlopen(req)
thePage = response.read()


Referencias:

lunes, febrero 04, 2008

HTML5 or XHTML 2.0

He leido un artículo interesante que compara HTML5 contra XHTML 2.0 [vía].

martes, enero 29, 2008

Brad Fitzpatrick

De una cosa que se oye hablar últimamente: opensocial.
Y tambien de openid.

Detrás de ambos proyecto hay un nombre común: Brad Fitzpatrick.

jueves, enero 24, 2008

¿Escalan bien los lenguajes dinámicos?

A través de este post de barrapunto, llego a éste articulo de The Server Side.
Es de interesante lectura, no solo por el artículo, sino ademas por todas las referencias que contiene.

Parece que todo viene a colacion del proyecto chandler.

TinyURL

Hoy me he encontrado una pequeña herramienta web, que puede ser muy util, TinyURL. No sólo proque nos puede ayudar a hacer mas manejables ciertas urls, sino porque nos puede permitir no favorecer el algoritmo de google, por el tema del enlazado. Se sepa... ;). O bien por lo que sea porque queramos enmascarar una url hasta el momento de pincharla.

miércoles, enero 16, 2008

Lista de año

En el 2007 mi lista favorita sin dudarlo ha sido python-es.

martes, enero 15, 2008

Blog favorito 2007

Sin dudarlo, Ismael El-Qudsi.

lunes, enero 14, 2008

Ha surgido un thread muy interesante en python-es a raiz de que python ha sido declarado por TIOBE lenguaje del año 2007.

viernes, enero 11, 2008

TIOBE Declares Python the Programming Language of 2007.

Impresionante el avance de Lua.

sábado, enero 05, 2008

¿que nos deparará el 2008 en cuanto a buscadores?

Un post interesante de dirson al respecto.

jueves, noviembre 15, 2007

Python en Linux-magazine

El número 32 de Linux Maganize va dedicado a python [vía la lista python-es].

miércoles, noviembre 14, 2007

Parseando CSS en python revisited

Una tercera entrada sobre el tema. Las anteriores:
Debido a la lentitud de cssutils (usé la versión 0.9.1b3) pobré libcroco y las diferencias de tiempo eran brutales (en un ejemplo real, pues ('real time') de procesar en 0,1 seg. a 0,4 seg.

Para la funcionalidad que necesito, me valen ambas, con lo cual en mi caso la elección está clara, ya que el tiempo de procesamiento me importa. Mi uso de la librería es muy rudimentario. Lo que realmente me interesa es el parseo en si, que me lo den, luego yo ya manejaré los datos a mi antojo...

Ahora bien, si el tiempo no te importan pues lo suyo es usar csstuils, porque libcroco te obliga a implementar bindings, ya que es C.

Con respecto a cssutils, comentar que ultimamente veo que el proyecto ha estado muy activo (van por la version 0.9.4a3), y que ahora está alojado en google code.

Bindings a libcroco
Para los bindings usé swig. No por decisión propia, sino porque ya lo usabamos.... No se si es lo mejor, pero es lo que hay.

En un primer intento lo que hice fue intentar atacar el interfaz de la librería. ¡Piiiiiip! Error.
Inabordable.
La solución fué hacer un recubrimiento en C sobre la librería, y hacer los bindings para ese recubrimiento.

En mi caso, el fichero de interfaz quedó como sigue:

%module css2av

%header %{
#include "css2av.h"
%}



typedef struct
{
char *selector;
char *declaration;
} AVStyleRule;

extern long numRules;


void freeResouces();
void process(const char *buffer,
long len
);
AVStyleRule *getRule(int index);


%include cpointer.i
%pointer_functions(AVStyleRule, AVStyleRulePtr)

Ya veis que api complejo y sofisticado me gasto ;)...
¿Que es necesario para generar los bindings?
  • Pues los .h y .c del codigo c
  • el .i (el codigo mostrado)
Procedimiento para generarlos:
  • Generar los bindings: swig -python [fichero]
  • Compilar nuestro código de interfaz (el .c para obtener el .o)
  • Compilar el código de los bindings (fichero [nombre_interfaz]_wrap.c ). Para compilarlo usar la opción -c del gcc e incluir con -L .../python y -L .../python/config
  • Generar la librería: gcc -shared [nombre].o [nombre]_wrap.o -o _[nombre].so -L[ruta] -lcroco-0.6 -lglib-2.0 -lxml2 -lz -lm
Ejemplo de uso:

import css2av

css2av.process(data,len(data))

for i in range(css2av.cvar.numRules):
styleRule = css2av.getRule(i)
print "Regla:",
css2av.AVStyleRulePtr_value(styleRule).selector,
css2av.AVStyleRulePtr_value(styleRule).declaration

css2av.freeResouces()


Como se puede apreciar, el código no es muy pythoniano. La solución es hacer un recubrimiento a los bindings mas pythoniano.

lunes, noviembre 12, 2007

Una Guía de estilo de código Python. Merece la pena su lectura.