A Django site.
Setiembre 24, 2011
» Lighting talks en PyConAr 2011 – día 2

Ayer publiqué el resumen de las lighting talks del primer día. Estas son las del segundo.

24 de septiembre de 2011

Mariano Reingart – gui2py

http://code.google.com/p/gui2py/

Una idea: usar web2py para hacer aplicaciones de escritorio usando wx.html.HtmlWindow.

Gabriel – Tornado y Hadoop, integración en el mundo real – Mercadolibre

Tornado: servidor web Python asincrónico
Redis: sort of memcache
Apache Hadoop

Gonzalo – SugarLabs Argentina

http://ar.sugarlabs.org

Sugar es un entorno de actividades que corren en las OLPC. 95% Python. Mañana y pasado se juntan a programar y a enseñar en Junín.

Alan Etkin – math2py

http://sourceforge.net/projects/math2py/

Aplicación web para matemáticas sobre web2py. Entre las herramientas incluye: resolver sistemas lineales, funciones matemáticas, gráficos con resultados.

TeMiro?

http://temiro.tv

Hagamos un Cuevana que no necesite ni flash ni extensiones. Usan videoJS, que permite que los navegadores sin soporte para HTML 5 puedan ver videos igualmente. info@devecoop

Nico César – El futuro de Python

Nos contó sobre la biblioteca mindread. (un poco de humor, si no vinieron a verlo, se lo perdieron).

Sorteo

Se sorteó un un Cuchillo de PyConAr entre las personas que viajaron más de 1000 kms para participar. Adolfo de Santiago de Chile, Manuel de España, uno de Rusia, Ezequiel de Tucumán, Guillermo de La Rioja, Pablo de Montevideo (casi 1000), y otros mas…

random.choice(lista_con_los_nombre)

Damián Avila – Tradeo de pares con Python

Python para resolver problemas de finanzas. Modelos matemáticos con base probabilística. 2 series financieras y cointegración.

Diego MascialinoCDPedia

http://python.org.ar/pyar/Proyectos/CDPedia

Un proyecto que busca que Wikipedia pueda ser visto en lugardes sin acceso a Internet. Este año se resolvió el problema de tener dumps actualizados de la enciclopedia. Salió la versión 0.7 que es distribuida por Educ.ar.

Guillermo Narvaja – ISO 9001 menos burocrática

Implementaron ISO 9001 en la empresa Fierro. En lugar de documentos impresos usaron documentos de texto, rst, con revisión de versiones y otras herramientas de Software Libre.

Juan Pablo y Pedro – Onapsis Bizploit

http://www.onapsis.com/

Una startup orientada a la seguridad en aplicaciones críticas de negocios. Fork de sapyto, primer framework para hacer penetration tests de SAP. Está desarrollado como prueba de concepto para demostrar la existencia de riesgos.

La arquitectura consiste en un core con plugins: discoveres, exploiters.

Ricardo Kirkner – ConfigGlue

https://launchpad.net/configglue

Es una librería para mantener la configuración de un programa. Código Python, por lo que permite validar tipos, heredar, standares xdg. Integra ConfigParser y OptionParser.

Manuel Quiñones – Fork de MyPaint

Le agrega a MyPaint la posibilidad de editar animación.

Fotos por César Portela:

P1020121 P1020124 P1020125 P1020127 P1020128 P1020135 P1020139 P1020141 P1020142 P1020143 P1020144 P1020146 P1020148 P1020153 P1020155 P1020157 P1020158 P1020159 P1020164 P1020168 P1020169

Setiembre 23, 2011
» Lighting talks en PyConAr 2011 – día 1

Las lighting talks, ya clásica en las conferencias de Python, son charlas de 5 minutos. Los disertantes se anotan en un papal fuera del aula unos minutos antes del comienzo. Lo bueno de la modalidad es lo siguiente: en 5 minutos podés enterarte de algo muy interesante, ¿y que pasa si que el que habla es un plomo? No importa, en menos de 5 minutos se va.

Estas son notas rápidas tomadas mientras los disertantes hablaban.

23 de septiembre de 2011

Natalia Bidart – Ubuntu One en el desktop

https://launchpad.net/ubuntuone

Ubuntu one tiene UI en GTK (la distribuida hoy en los Cds de Ubuntu) y en QT (reemplazará a la versión actual). En el código fuente se puede ver como tener en el mismo repositorio el soporte para ambos toolkits.

Diego Sarmentero – Ninja IDE

http://ninja-ide.org/

A partir del 22 de octubre estará abierto el primer concurso de plug-ins para Ninja IDE. Primer premio 250 u$s.

Facundo Batista – Cómo generar un ejecutable con sistema Python

Tenemos un paquete con un módulo con una función. 3 líneas de código sirven como prueba de concepto, es lo mismo si tuviésemos un sistema muy grande. Se necesita un __main__.py que ejecute el sistema. Hacemos un zip con todo.

( echo ‘#!/usr/bin/env python’ ; cat foo.zip) > saludo
chmod +x saludo

Y listo! Podemos ejecutarlo con:

./foo

Idea original de John Lenton.

Joaquin Sorelliano – Cooperativismo

Hay varias cooperativas que producen Software Libre en el país: Elvex, Devecoop, Unixono, Gcoop y otras.

Juan Bautista Cabral – Revista PET

http://revista.python.org.ar/

La revista pretende documentar los eventos La revista tiene ISSN, lo cual la hace citable.

Margarita Manterola – Por qué no usar OpenERP

Es un ERP o un framework para desarrollar sistemas de gestión. Se presenta como una tentación, multi todo, muchos módulos, usado por muchas empresas, hecho en Python y es Software Libre.

La verdad: es chico, usa un ORM horrible, no se pueden hacer búsquedas por JOIN, los objetos no se actualizan y hay que releerlos de la BD, la herencia está mal implementada. Muchos dolores de cabeza. El cliente GTK tiene que estar todo el tiempo conectado al servidor para redibujarse. La interfaz de usuario está mal diseñada. El equipo de desarrollo elimina características de una versión a otra, con documentación desactualizada, “comunidad” poco amigable (no acepta parches) y el código es lo peor.

Tryton, fork de OpenERP. No segura de que sea una alternativa. Empezar uno desde cero? Si, pero no cada uno el propio, juntémosnos.

Manuel Quiñones – Animación Quebracho

http://animacionquebracho.org.ar/

Un dibujo animado que se está desarrollando con financiamiento de la provincia de Santa Fe. Cuenta la historia de la provincia, será CC y está hecho con Software Libre.

Evgeny Fadeev (from Russia) – Python @ StartupChile

http://www.startupchile.org

Programa del gobierno chileno. Le da a cada equipo 40000 u$s. Le da Visa a extranjeros. Les presenta empresarios chilenos y otros beneficios. Les dan oficinas gratis en Santiago.

Primero hubo 110 proyectos. Luego 154 nuevos proyectos de 33 países. Muchos de los proyectos están hechos en Python. Hay empresas contratando.

El proyecto de Evgeny es AskBot, un sitio de Q&A.

Apply. La próxima ronda empieza en octubre.

Martín Gaitán – PyQuery

http://pypi.python.org/pypi/pyquery

jquery-like library. Más simple y potente que BeautifulSoup para scrappear la web.

Martín y Juan Catalano – Streema

http://streema.com/

Es una startup, un sitio web, una red social para escuchar radios de todo el mundo. Hecho con Django y Eventlet. La empresa tiene 4 años y hace poquito se hizo rentable.

Kragen Javier Sitager

Presentación de la charla del día siguiente: Utilizando PyGame para instalaciones artísticas interactivas. No se pudo hacer por problemas técnicos.

Ale Cura – PyCamp

http://python.org.ar/pyar/PyCamp/

Un “campamento” en dónde los Pythonistas argentinos se juntan a trabajar en el medio de la naturaleza.

Fotos por César Portela:

P1020041 P1020044 P1020045 P1020062 P1020063 P1020064 P1020065 P1020066 P1020067 P1020069 P1020070 P1020071 P1020072 P1020077 P1020078 P1020080 P1020081 P1020082 P1020083 P1020085 P1020086 P1020087 P1020093 P1020094

Mayo 9, 2010
» Charla: Entendiendo Decoradores en Python

Ayer di esta charla en el primer PyDay en Rafaela. Estuvo muy bueno, la organización se pasó y tuvieron muy buena asistencia de estudiantes de la universidad y programadores de la ciudad.

Les dejo el pdf de la charla y una foto grupal del final del día:

023

Mayo 2, 2010
» 8 de mayo: Python Day en Rafaela

El próximo sábado se va a desarrollar en la ciudad de Rafaela un Python Day, un día de charlas para que quienes no conozcan Python puedan acercarse al lenguaje. Vamos a tener muchas charlas introductorias y esperamos pueda aprovechar este evento tanto la comunidad universitaria como la ciudad en general.

http://www.pyday.com.ar/rafaela2010/

Por mi parte voy a estar colaborando con una charla nueva: Entendiendo Decoradores en Python. Esperemos salga bien :)

El Python Day es un evento organizado por PyAr con el apoyo de la Universidad Católica de Santiago del Estero, Departamento Académico Rafaela.

El evento dura un día donde se darán pequeños cursos y charlas relacionadas a este lenguaje que de a poco va a haciendo su lugar entre los desarrolladores. Tenemos como intención hacer un espacio en donde cualquier persona interesada pueda acercarse para preguntar, aprender y experimentar con estas herramientas.

El evento se llevará a cabo acá a partir de las 9:00 de la mañana.

¿Qué es Python?

Python es un lenguaje de programación interpretado creado por Guido van Rossum en el año 1990.

En la actualidad Python se desarrolla como un proyecto de código abierto, administrado por la Python Software Foundation. La última versión estable del lenguaje es la 2.6 (01 de octubre de 2008).

Fuente: Wikipedia

Quiero participar… ¿Qué Hago?
Si lo que querés es asistir a las charlas, solo aparecete por la universidad el 8 de mayo a partir de las 09:00 y listo (por favor, si es posible, registrate previamente por web)

Abril 28, 2010
» Python Taint Mode en OWASP App Sec Estocolmo 2010

En febrero de este año estuve trabajando mucho con Alejandro Russo para mejorar la librería de Taint Mode en Python en la que empecé a trabajar el año pasado. De este trabajo surgió un paper que enviamos al congreso OWASP AppSec Research 2010 – Stockholm, Sweden y hace unos días nos avisaron que fue aceptado:

A Taint Mode for Python via a Library

Si Dios quiere, voy a estar allá presentándolo.

Abril 6, 2010
» La historia de Python: El Gran (o Enorme) Renombrado

El siguiente texto es una traducción del artículo The Great (or Grand) Renaming de Guido van Rossum publicado en http://python-history.blogspot.com/.

El Gran (o Enorme) Renombrado

Cuando creé Python, siempre lo imagine como un programa autónomo, enlazado ocasionalmente con bibliotecas de terceros. Por lo tanto, en el código fuente, se definían nombres globales con total libertad, como “object”, “getlistitem”, “INCREF” y muchos otros mas. Cuando la popularidad de Python se incrementó, la gente comenzó a pedir una versión “embebida”, que fuera también una biblioteca enlazable a otras aplicaciones – de una forma similar en la que Emacs incorpora un interprete de Lisp.

Desafortunadamente, la integración se complicaba por conflictos entre los nombres globales de Python y los definidos por la aplicación – “object” era especialmente popular. Para lidiar con ese problemas se eligió una convención, por la cual todos los nombre globales comenzarían con “Py” o “_Py” (para los internos que tenían que ser globales por razones técnicas) o “PY” (para las macros).

Por razones de compatibilidad hacia atrás (ya que había muchos módulos de extensión de terceros) y para facilitar la transición a los desarrolladores del núcleo (que tenían los viejos nombres enquistados en sus mentes) hubieron dos fases. En la fase uno, el enlazador aceptaba los nombres antiguos, pero el código fuente usaba los nuevos, que eran traducidos a los antiguos usando muchas macros del pre procesador de C. En la fase dos, el enlazador veía los nuevos, pero, para beneficio de los módulos de extensión que todavía no habían sido portados, otro conjunto de macros traducía los viejos a los nuevos. En ambas fases el código podía incluir ambos, y funcionar correctamente.

Investigué un poco la historia en los logs de Subversion. Encontré la revisión r4583 del 12 de enero de 1995, que marca el comienzo de la fase dos, introduciendo los nuevos nombres a los archivos de encabezado. Pero en diciembre de 1996 el renombrado de los archivos fuentes “.c” seguia en marcha. En ese momento el renombrado parecía haber cambiado de nombre, los comentarios de registro lo llamaban “El Enorme Renombrado”. Las macros de compatibilidad hacia atras fueron finalmente removidos en mayo de 2000, como resultado de la liberación 1.6. El comentario de r15313 celebra este evento.

La mayor parte del crédito se lo llevaron Barry Warsaw y Roger Masse, que participaron en la desagradable tarea de renombrar los contenidos de archivo, tras archivo, tras archivo… (aunque con la ayuda de un script). También ayudaron en la tediosa tarea de agregar test unitarios para gran parte de la biblioteca estándar.

Wikipedia hace referencia a un anterior Gran Renombrado, que aparentemente consistió en el renombre de grupos de USENET. Probablemente lo recordaba de forma inconsciente cuando lo llamé asi. También encontré algunas referencias a un Gran Renombrado posterior en Sphinx, el paquete utilizado para generar la documentación de Python. Zope también tuvo uno, y algunos debates recientes de Py3k utilizan el término para el cambio de PyString a PyBytes (aunque es menor, comparado con los otros).

Los Grandes o Enormes cambios de nombres son a menudo eventos traumáticos para las comunidades de desarrollo de software, porque requieren que los cerebros de los programadores sean recableados, la documentación reescrita y se complica la integración de parches creados antes, pero aplicados después (esto es especialmente problemático cuando existen ramas no renombradas).
Traducido por Joaquín Sorianello.
Revisado por Juan José Conti.
Si encontrás errores en esta traducción, por favor reportalos en un comentario y los corregiremos a la brevedad.

Todas las traducciones de esta serie pueden encontrarse en La historia de Python.

Abril 3, 2010
» Servidor SMTP para hacer pruebas

Cuando estamos programando, muchas veces necesitamos de un servidor de mails para que nuestro programa envíe todo tipo de mensajes: reportes de error, avisos, passowords luego de una gesistración, “contact us”, etc…

Muchas veces no se tiene un servidor SMTP instalado en la computadora de desarrollo, pero si tenemos Python instalado, podemos ejecutar el siguiente comando y tener un servidor de prueba en el que en lugar de enviar los mails porla red, se imprimen por la salida standar:

python -m smtpd -n -c DebuggingServer localhost:25

Abril 1, 2010
» La historia de Python: Módulos cargados dinámicamente

El siguiente texto es una traducción del artículo Dynamically Loaded Modules de Guido van Rossum publicado en http://python-history.blogspot.com/.

Módulos cargados dinámicamente

La arquitectura de Python permitió, desde un principio, escribir módulos de extensión escritos en C de una forma sencilla. Sin embargo, en los primeros días, la tecnología de carga dinámica era tan oscura que las extensiones tenían que ser enlazadas estáticamente en el interprete de Python, en tiempo de compilación. Para hacer esto, lo módulos de extensión tenían que ser agregados a un script de shell que era usado para generar el Makefile para Python y todos su módulos de extensión.

Aunque este enfoque funcionaba para pequeños proyectos, la comunidad de Python comenzó a producir nuevos módulos de extensión a un ritmo no esperado, y demandaban que los módulos pudiesen ser compilados y cargados en forma separada. Poco después, las interfaces a las APIs de enlace dinámico, propias de cada plataforma, permitieron que la declaración import busque una biblioteca compartida en disco, de forma similar que un archivo “.py”. La primera mención de la carga dinámica en los logs del CVS, data de enero de 1992 y el soporte para la mayoría de las plataformas llego a fines de 1994.

El soporte de enlace dinámico probó ser muy útil, pero fue una pesadilla de mantener. Cada plataforma usaba una API diferente y algunas plataformas tenían adicionales. En enero de 1995, el soporte para enlace dinámico fue reestructurado, de forma tal que todo el código fue concentrado en un solo archivo fuente. Sin embargo, este enfoque resulto en un largo archivo abarrotado de directivas condicionales de compilación (#ifdef). En diciembre de 1999, fue reestructurado de nuevo, con la ayuda de Greg Stein, para que el código correspondiente a cada plataforma quede ubicado en un archivo específico para cada una (o familia de estas).

Aunque Python soportaba la carga dinámica de módulos, el procedimiento para construirlos, a menudo seguía siendo un misterio para muchos usuarios. Un número cada vez más grande de usuarios fueron construyendo módulos, especialmente con la introducción de herramientas como SWIG. No obstante, un usuario deseoso de distribuir un modulo de extensión enfrentaba grandes obstáculos para lograr que el modulo compile en todas las combinaciones de plataformas, compiladores y linkers. En el peor escenario posible, un usuario tenía que escribir su propio Makefile y script de configuración para establecer los flags correctos para el compilador y el linker. Además, requería que los usuarios finales tuviesen una distribución de Python con el código fuente.

Finalmente, se creo una herramienta para construir las extensiones, llamada distutils, que permitió construir e instalar los módulos de extensión en cualquier plataforma. Las opciones necesarias para el linker y el compilador están escritas desde el makefile de Python a un archivo de datos, que es consultado por distutils cuando construye módulos de extensión. Escrito en gran parte por Greg Ward, las primeras versiones de distutils fueron distribuidas en forma separada, para dar soporte a versiones viejas de Python. Desde Python 1.6 está integrado en las distribuciones, como un modulo de la biblioteca estándar.

Cabe destacar que distutils hace mucho mas que simplemente construir módulos de extensión desde código fuente en C. Puede también instalar módulos y paquetes de Python puro, crear instaladores ejecutables para Windows y correr herramientas de terceros como SWIG. Desgraciadamente, su complejidad ha causado que sea maldecida por mucha gente y no reciba la atención que se merece a la hora de mantenerla. Como resultado, recientemente, las alternativas de terceros ( especialmente ez_install, también llamada “eggs”) se hicieron mas populares, desgraciadamente causando fragmentación en la comunidad de desarrolladores, así como quejas cuando no funcionan. Parece que el problema en toda su generalidad es inherentemente difícil.
Traducido por Joaquín Sorianello.
Revisado por Juan José Conti.
Si encontrás errores en esta traducción, por favor reportalos en un comentario y los corregiremos a la brevedad.

Todas las traducciones de esta serie pueden encontrarse en La historia de Python.

Marzo 3, 2010
» os.path en el settings.py de Django para mayor comodidad

En el archivo de configuración settings.py de un proyecto Django, por lo general tenemos que setear variables como MEDIA_ROOT o STATIC_DOC_ROOT. Su contenido en una instalación Windows suele ser algo como: 'C:\Windows\camino\hasta\mi\projecto'. Y en Linux: '/home/usuario/camino/a/mi/proyecto'. El problema surge cuando el proyecto es desarrollado en varias máquinas a la vez, y con distintos sistemas operativos. Más aún, si hacemos lo anterior, seguramente versionaremos el proyecto y con él, al archivo de configuración. No sería raro que tras una actualización, el archivo se actualice con los valores que puso algún compañero de trabajo.

Mi solución es definir primero una variable para el proyecto:

PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))

Luego podemos usarla para definir el path absoluto a la carpeta con archivos de media:

MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')

nuestros templates:

TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(PROJECT_PATH, 'templates')
)

o cualquier otra variable de configuración que requiere una ruta de directorios.

Con esta solución podemos cambiar el proyecto de carpeta, disco o computadora y seguirá funcionando.

Febrero 6, 2010
» Aplicar un decorador a todas las funciones de un módulo en Python

En la lista de PyAr preguntaron si había alguna forma de aplicar un decorador a todos las funciones de un módulo. Envié una solución sin probarla, que al verla unos días más tarde parece bastante buena :)

La comento aquí con un ejemplo. modulo.py contiene definiciones de funciones:

def a():
    pass

def b():
    print 42

def c():
    a()
    b()

y decoradores.py un decorador que imprime el nombre de la función llamada:

def nombrador(f):
    def inner(*a, **kw):
        print "Ejecutando %s" % f.__name__
        return f(*a, **kw)
    return inner

(Si no sabés lo que es un decorador, podés leer mi post Decoradores en Python I: Introducción)

En lugar de modificar las definiciones de funciones en modulo.py para aplicar el decorador a cada una de las funciones, ya sea usando el azúcar sintáctica de Python:

@nombrador
def a():
    ...

o mediante una llamada a la función:

a = nombrador(a)

podemos agregar el siguiente código al final de modulo.py:

for n,v in locals().items():
   if inspect.isfunction(v) and n != 'nombrador':
       locals()[n] = nombrador(v)

Vamos a explicarlo:

la llamada a la función built-in locals retorna un diccionario representando el espacio de nombres local: cada clave es un string representando el nombre de un objeto y cada valor es el objeto en si. Iteramos sobre la lista de pares (key, value) del mencionado dict y por cada uno verificamos si:

a) es una función (inspect.isfunction es apropiado para esto)
b) el nombre no es el del decorador que queremos aplicar (para no aplicar el decorador sobre si mismo!)

Si las condiciones a y b se cumplen, podemos guardar en el diccionario del espacio de nombres, bajo el nombre de la función que cumplió las condiciones, una versión decorada de la misma.

Agregamos algo más de código a modulo.py para que se llame a las funciones cuando lo ejecutemos:

if __name__ == '__main__':
    a()
    b()
    c()

Esta es la salida obtenida:

juanjo@fenix:~/python/muchosdecos$ python modulo.py
Ejecutando a
Ejecutando b
42
Ejecutando c
Ejecutando a
Ejecutando b
42

¿Querés probarlo? Bajá muchos.zip

Nota: para acceder a locals() no se puede utilizar iteritems por que el diccionario cambia durante la ejecución.

Enero 8, 2010
» Generación espontanea de código

Software does not make itself. Code does not spontaneously come from the ether of the universe.

800px-Big_bang
El párrafo completo:

Software does not make itself. Code does not spontaneously come from the ether of the universe. Python is no exception to this rule. Since Python made its public debut back in 1991 many people beyond the BDFL (Benevolent Dictator For Life, Guido van Rossum) have helped contribute time and energy to making Python what it is today; a powerful, simple programming language available to all.

Fuente: http://python.org/dev/intro/

» Big refactoring en dyntaint.py

Ayer llevé acabo un refactoring importante en mi proyecto Taint Mode para Python.

En resumen: dyntaint.py es un módulo que permite seguirle la huella a datos que ingresan a un programa con el objetivo de evitar que lleguen a ciertas áreas sensibles. Por ejemplo, que “42 or 1=1″ no llegue a una consulta SQL que se ejecutará contra una base de datos.

Si lo anterior no te dice nada, te recomiendo que leas mi presentación sobre el tema.

Hasta hoy, el registro de qué variables estaban manchas con qué tipo de manchas en una corrida del programa se llevaba en una estructura de datos auxiliar llamada TAINTED. Básicamente un diccionario en el cual cada clave se corresponde con un tipo de mancha (o vulnerabilidad), y cada valor es un conjunto de variables manchadas con el tipo de mancha de la clave correspondiente.

El refactoring consistió en cambiar de este esquema a uno en el cual cada variable manchada tiene un atributo (taints) que es un conjunto de identificadores de manchas. Entonces si antes tenía algo como:

{XSS: set(['manchado1', 'manchado2']),
SQLI: set(['manchado1'])}

ahora tengo:

>>> manchado1.taints
set([XSS, SQLI])
>>> manchado2.taints
set([XSS])

La revisión 59 también incluye algunas otras limpiezas. Para ver los cambios:

svn diff -r 58:59 http://svn.juanjoconti.com.ar/dyntaint/

Después de hacer las modificaciones necesarias, y corregir errores, las pruebas corren ok:

Ran 84 tests in 0.006s

OK

Podemos discutir los cambios en los comentarios.

Diciembre 31, 2009
» Decoradores en Python (III) – Clases decoradoras

Siguiendo con la serie de posts sobre decoradores en Python, y fiel al espíritu que los originó (ir mostrando lo que voy aprendido a medida que necesito resolver problemas específicos o descubro aplicaciones concretas) hoy les traigo un nuevo uso para los decoradores en Python: funciones caché.

Anteriormente: Decoradores I, Decoradores II.

Funciones caché

Una función caché[0], es aquella que siempre que se le pide que compute un resultado para un grupo de parámetros dado, primero se fija en una memoria interna si no realizó ya el cálculo. Si ya lo hizo, retorna el valor computado anteriormente. Si aún no lo hizo, computa el valor, lo guarda en una memoria interna y luego lo retorna.
Esta técnica es muy útil en funciones que requieren un cómputo intensivo y obtener un resultado lleva mucho tiempo. Permita acelerar sustancialmente los tiempos de ejecución a cambio de utilizar más memoria.

La siguiente es una forma de implementarlo en Python para un computo en particular:

cache = {}
def fmem(arg):
    if arg in cache:
        print "Recuperando valor de la memoria"
        return cache[arg]
    else:
        r = (arg ** 10) * (arg ** -5)
        cache[arg] = r
        return r

Como memoria se utiliza un diccionario y el argumento de la función fmem es la clave del diccionario[1].

Este es el resultado de utilizarla en el intérprete interactivo:

>>> fmem(1)
1.0
>>> fmem(2)
32.0
>>> fmem(2)
Recuperando valor de la memoria
32.0

Decoradores con estado

En esta implementación, la técnica de memorización se mezcla con el cálculo que era el objetivo original de la función. Si queremos aplicar la técnica sobre distintas funciones vamos a tener que entrometer la implementación de la caché en todas las funciones. Peor aún, si en el futuro se quiere realizar un cambio en la forma de almacenar y recuperar los valores almacenados, ¡tendríamos que modificar todas las funciones! La forma de resolver estos problemas es implementando un decorador que agregue esta funcionalidad a las funciones decoradas: resolvemos ambos problemas, el de intrución y el de mantenibilidad. Todo el código que provee esta funcionalidad extra es encapsulado en el decorador.

Las funciones decoradoras, como las que vimos en los anteriores artículos, no nos sirven para esta tarea. Necesitamos un decorador que pueda almacenar un estado. Ya que cualquier callable puede ser un decorador, implementaremos el decorador mediante una clase.

Funciones caché con clases decoradoras

La definición de la clase decoradora consiste en dos métodos:

  • un método de inicialización, dónde se inicializa el atributo cache con un diccionario vacío y se guarda una referencia a la función decorada.
  • un método __call__ que será ejecutado cuando se llame a la función decorada.
class mem(object):

    def __init__(self, g):
        self.cache = {}
        self.g = g

    def __call__(self, arg):
        if arg in self.cache:
            print "Recuperando valor de la memoria"
            return self.cache[arg]
        else:
            r = self.g(arg)
            self.cache[arg] = r
            return r

Luego, lo único que resta es decorar todas las funciones que querramos “dotar de memoria” para obtener mejoras de performance en su ejecución:

@mem
def f(arg):
    return (arg ** 10) * (arg ** -5)

La salida obtenida al ejecutar la función decorada en el intérprete interactivo es la misma qué en el ejemplo anterior:

>>> fmem(1)
1.0
>>> fmem(2)
32.0
>>> fmem(2)
Recuperando valor de la memoria
32.0

Más

La implementación del decorador mem solo sirve para decorar funciones que reciben un único argumento. Podemos mejorar su definición para que pueda decorar funciones con cualquier número de argumentos:

class mem2(object):

    def __init__(self, g):
        self.cache = {}
        self.g = g

    def __call__(self, *args):
        if args in self.cache:
            print "Recuperando valor de la memoria"
            return self.cache[args]
        else:
            r = self.g(*args)
            self.cache[args] = r
            return r
@mem2
def f2(arg1, arg2):
    return (arg1 ** 10) * (arg2 ** -5)

Notas

[0] Se puede leer más sobre este concepto en Caching Function Results:Faster Arithmetic by Avoiding Unnecessary Computation de Stephen E. Richardson [SMLI TR-92-1]
[1] Esta implementación tiene la limitación de que si el argumento de la función es un objeto mutable, no podrá ser usado como clave de un diccionario y se lanzará una excepción.

Noviembre 2, 2009
» Conjuntos en Python

Cuando estaba preparando mi charla introductoria a Python, le pasé mis slides a un amigo para que me diga su opinión y una de las cosas que me dijo fue

Nunca senti que set sea algo nativo de python, le daria mas importancia a los diccionarios, aunque tal vez tu publico este mas interesado en sets, no lo se.

Me sorprendió el comentario. Para mi, set es un tipo de dato muy útil y poderoso. En este post voy a intentar hacer una apología de set, el tipo de dato que incorpora Python para representar la noción matemática de conjunto.

Presentación

Un objeto set es una colección sin orden de objetos hasheables. Puede contener objetos de todos los tipos inmutables de Python, pero no los contenedores mutables como listas. También puede contener objetos de clases definidas por el usuario (Los objetos instancias de clases definidas por el usuario son por defecto hasheables.).
Los conjuntos se pueden crear, por ejemplo, a partir de una lista. Podemos quitar elementos (al azar o uno en concreto) o agregarlos:

>>> heladera = ['huevo', 'huevo', 'queso', 'leche', 'pera', 'pera', 'pera']
>>> alimentos = set(heladera)
>>> alimentos
set(['queso', 'leche', 'huevo', 'pera'])
>>> alimentos.pop()
'queso'
>>> alimentos.remove('leche')
>>> alimentos
set(['huevo', 'pera'])
>>> alimentos.add('empanada')
>>> alimentos
set(['empanada', 'huevo', 'pera'])

Prueba de pertenencia

Otra función muy común y útil es probar la pertenencia de objetos al conjunto:

>>> 'empanada' in alimentos
True
>>> 'leche' in alimentos
False
>>> 'leche' not in alimentos
True

Iterar sobre conjuntos

Podemos interar sobre conjuntos de la misma forma que lo hacemos sobre listas:

>>> for a in alimentos:
...     "Debo comer " + a
...
'Debo comer empanada'
'Debo comer huevo'
'Debo comer pera'

Operaciones sobre conjuntos

Los conjuntos en Python soportan las operaciones típicas de conjuntos: restas, intersección, unión y diferencia simétrica (los elementos que están en uno de los conjuntos, pero no en ambos). Repasar operaciones con conjuntos.

>>> frutas = set(['banana', 'naranja', 'pera'])
>>> frutas - alimentos
set(['banana', 'naranja'])
>>> alimentos - frutas
set(['huevo', 'empanada'])
>>> frutas & alimentos
set(['pera'])
>>> frutas | alimentos
set(['huevo', 'empanada', 'pera', 'banana', 'naranja'])
>>> frutas ^ alimentos
set(['huevo', 'empanada', 'banana', 'naranja'])

También podemos preguntar sin un conjunto es subconjunto de otro. En los ejemplos se utiliza set(), el conjunto vacío:

>>> alimentos < set()
False
>>> set() < alimentos
True
>>> set() > alimentos
False
>>> alimentos <= alimentos
True

El problema de las dos comisiones

Este problema está basado en un caso real y lo escuché en la charla Escribí menos código, pensá como un (buen) matemático de Gustavo Carmona (FCEYN - UBA) bio y Matías A Graña (FCEyN - UBA) bio.

Se tienen dos archivos de textos con una lista de e-mails en cada uno. Cada archivo tiene los mails de los funcionarios de una comisión; los archivos no están bien depurados, por lo que pueden contener direcciones repetidas; hay funcionarios trabajando en las dos comisiones. Luego de una reunión en la que trabajaron ambas comisiones, se generó un material que se necesita enviar a todos los participantes. ¿Cómo obtener la lista de destinatarios?

archivo 1
dir1@mail.com
dir2@mail.com
dir3@mail.com
dir1@mail.com
archivo2
dir21@mail.com
dir23@mail.com
dir3@mail.com
dir1@mail.com

Queremos una tercera lista que tenga la primera más la segunda, pero que no estén repetidos.

El enfoque tradicional que utilizaría un programador para resolver este problema mediante bucles es:

def unionlarga(l1, l2):
    l3 = []
    for x in l1:
        if not x in l3:
            l3.append(x)
    for x in l2:
        if not x in l3:
            l3.append(x)
    return l3

Supongamos que ya tenemos los archivos leídos y almacenamos el contenidos en listas:

>>> unionlarga(archivo1, archivo2)
['dir1@mail.com', 'dir2@mail.com', 'dir3@mail.com',
'dir21@mail.com', 'dir23@mail.com']

La solución es genérica para cualquier lenguaje. Sin embargo, puede lograr una mejor solución utilizando sets en Python:

>>> list(set(archivo1) | set(archivo2))
['dir21@mail.com', 'dir3@mail.com', 'dir2@mail.com',
'dir1@mail.com', 'dir23@mail.com']

Convertimos ambas listas a conjuntos (con lo que se eliminan los repetidos dentro de las listas), realizamos la unión de ambos conjuntos (con lo que se eliminan los repetidos entre listas y finalmente se convierte el resultado en una nueva lista.

Más sobre conjuntos en la referencia del lenguaje.

Octubre 21, 2009
» Charla Bienvenido a Python en Instituto Libre 09

flyingEl viernes por la tarde se llevó a cabo el evento Instituto Libre 09 en la ciudad de Coronda, más precisamente en el Instituto Superior de Profesorado Nº 6 Dr. Leopoldo Chizzini Melo.

Presenté una charla llamada Bienvenido a Python. Es una introducción al lenguaje de programación Python bastante práctica y con muchos ejemplos. Los slides están disponibles en formato pdf bajo una licencia CC. El documento fue generado a partir de un archivo de texto utilizando rst2pdf.

Setiembre 18, 2009
» Ejercicio 16 – proyecto Euler

De vez en cuando se me da por hacer saries de posts en el blog. Sagas. Una de las últimas fue la saga sobre resoluciones a problemas del proyecto Euler. Lo que intentaba era resolverlos con alguna característica interesante de Python y luego explicarla. Luego de los primeros, los ejercisios se volvieron más matemáticos y encontraba menos cosas interesantes de Python que comentar, así que dejé de postear mis soluciones. Acabo de encontrar esta entre mis archivos y creo que tiene algo de originalidad como para merecer ser publicada:

¿Cuál es la suma de los dígitos del número 2^(1000)?

>>> 2**1000
107150860718626732094842504906000[algunos números fueron intencionalmente borrados]
>>> a = 2**1000
>>> sum((int(x) for x in list(str(a))))
1366

¿A alguien se le ocurre otra forma?

Setiembre 6, 2009
» Charla relámpago: Comet en Twisted

Ayer en las charlas relámpago de PyCon Argentina 2009 mostré cómo utilizar Comet desde Twisted. Tenía un slide disparador que no pude mostrar por que OpenOffice no se abrió y como las charlas relámpago duran 5 minutos, no podía darme el lujo de investigar que pasaba.

“No importa”, dije, “de todas formas el slide tenía solo cuatro palabras”. Y para hacer justicia sobre las Leyes de Murphy publico aquí ese slide:

cometEl ejemplo que mostré en vivo puede bajarse del sitio web de Nevow/Athena.

Agosto 30, 2009
» El Tutorial de Python en Español

Hoy se ha publicado la versión HTML y PDF del tutoril oficial de Python en español. La traducción la hemos realizado varios voluntarios del grupo de usuarios de Python de Argentina.

http://python.org.ar/pyar/Tutorial
python-logo-master-v3-TM

Agosto 15, 2009
» Django Middleware

Mientras estudié el tema para hacer un experimento, traduje el 80% de la documentación oficial. La dejo aquí más algunos condimentos personales.

Middleware

Es un sub framework que permite modificaciones al sistema de procesamiento de request/response de Django. Es un sistema de plugins liviano y de bajo nivel que permite alterar globalmente las entradas y salidas de Django.

Cada componente middleware es responsable de hacer alguna función específica.

Activar componentes middleware

Para hacerlo, añadirlo a la lista MIDDLEWARE_CLASSES en la configuración de Django (settings.py). En esta lista, cada componente se representa por un string: el camino completo al nombre de la clase. Por ejemplo:

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)

En el tratamiento de requests y la generación de responses, existen dos faces:

1) Fase Request (se llama a los métodos process_request() y process_view())
2) Fase Response (se llama a los métodos process_response() y process_exception())

En la primera, las clases son aplicadas desde la primera a la última, según el orden de la lista mencionada. En la segunda fase, se aplican en orden inverso; podemos pensarlo como una cebolla:

middleware

Una instalación de Django puede funcionar sin ningún middleware, pero esto no es recomendado.

Para escribir middleware propios

Cada componente es una clase Python, que no tiene que extender a ninguna clase en particular y debe definir uno o más de los siguientes métodos.

process_request(self, request)

request es un objeto HttpRequest. El método es llamada por cada request, antes de que Django decida que vista ejecutar.

Debe retornar None o un objeto HttpResponse. Si retorna None, Django seguirá procesando el request, ejecutando los otros middlewares y luego la vista apropiada. Si retorna un objeto HttpResponse, Django no hará nada más, solo retornar ese objeto.

process_view(self, request, view_func, view_args, view_kwargs)

request es un objeto HttpRequest. view_func es la función Python que Django está por usar. (Es el objeto function, no el nombre de la función en un string). view_args es un alista de argumentos posicionales que serán pasados a la vista. Y view_kwargs es un diccionario de argumentos de palagra clave que serán pasados a la vista. Ni view_args ni view_kwargs incluye al primer argumento de la vista (request).

process_view() es llamado antes de que Django ejecute la vista. Debe retornar None o un objeto HttpResponse. Si retorna None, Django seguirá procesando el request, ejecutando otros process_view() y luego la vista apropiada. Si retorna un objeto HttpResponse, Django no hará nada más, solo retornar ese objeto.

process_response(self, request, response)

request es un objeto HttpRequest. response es un objeto HttpResponse retornado por una vista de Django.

process_response() debe retornar un objeto HttpResponse. Puede altener el objeto response dado o puede crear uno nuevo.

A diferencia de proces_request() y process_view(), este siempre es ejecutado.

process_exception(self, request, exception)

request es un objeto HttpRequest. exception es un objeto Exception lanzado por la vista.

Django llama a process_exception() cuando la vista lanza una excepción. process_exception() debe retornar None o un objeto HttpResponse. Si retorna un objeto HttpResponse, la respuesta es devuelta al navegador. De lo contrario, el sistema por defecto para manejo de excepciones entra en acción.

__init__

Por lo general estas clases no tienen estado; simplemente contienen a los anteriores métodos. Se puede usar el método __init__ pero se debe tener en cuenta que Django inicializa estas clases sin argumentos y que el método __init__ es llamado solo una vez, cuando el servidor web arranca.

Experimento

Con lo anterior en mente, me quedaron algunas dudas al respecto:

  • si modifico los argumentos de view_func en process_view y retorno None, ¿estos son pasados modificados a la vista?
  • si lo anterior es falso, puedo lograr el mismo efecto haciendo:
    def process_view(self,request, view_func, view_args, view_kwargs):
        # modificar request, view_args y view_kwargs
        return view_func(request, view_args, view_kwargs)

    ?

  • ¿puedo definir process_response de tal forma que examine response?

Agosto 2, 2009
» Una gran oportunidad de conocer Python!

El 4 y 5 de Septiembre se va a llevar a cabo en Capital Federal el evento PyCon Argentina 2009.

Organizado por la comunidad, con entrada libre y gratuita, se llevará a cabo en la Universidad de Belgrano. Habrá charlas plenarias, programadas y relámpago.


PyCon 2009 Argentina

¿Querés conocer Python? ¿Venís oyendo sobre este lenguaje por mucho tiempo y todavía no te animaste a probarlo? Esta es tu oportunidad! Te esperamos!