3.28.2010

Osadía

No hay vez que no vea un documental de construcciones u obras de ingeniería que no sienta una profunda envidia. Y siento envidia porque me doy cuenta que comparado con las empresas de software, ellos tienen claras muchas cosas que nosotros no tenemos.

Entre estas cosas hay una cosa que casi me hace llorar, y es que se tiene en cuenta al experto, si tienen que poner una plancha de un puente hay un -señor- ingeniero que es el que tiene los huevos pelados de pasarlas putas poniendo puentes, hay especialistas por cada una de las partes; especialista de hormigón, de neumática... y no se mueve ni un santo dedo si no hay un "ok" de esos expertos.

Otra de las cosas que me gusta es que saben hasta donde pueden llegar con más o menos deriva en el tiempo. Nadie pondría a 3 ingenieros a hacer un viaducto de 200m de altura y 500metros de largo y mucho menos les diría, esto tiene que salir sí o sí.

Sin embargo en el mundo del software, estoy ya acostumbrado a que se planteen objetivos sin sentido, metas a la vuelta de la esquina para algo que queremos denominar producto, planificaciones que no se ajustan en cuanto a personal...

Si algo he aprendido con el desarrollo de agroguía, es que el producto empieza a ser tal cuando tiene cierta madurez, se ha trabajado duro en los detalles. Esos que no se ven cuando se hacen planificaciones a boleo. Y esos detalles no son que la aplicación funcione -eso se da por hecho, que no es poco-, si no que sea simple de usar, que resuelva bien las situaciones inesperadas, que hable el mismo idioma que el usuario (no, no me refiero literalmente) y esos miles de cosas que hacen de una aplicación un producto.

Creo que uno de los grandes problemas del software es que no hay soporte material sobre el que basarse. Sabemos que llevar una piedra de 4toneladas de un sitio a otro no lo podemos hacer si no es con una grúa o un camión, es obvio, es algo palpable, sin embargo algo que no se puede tocar es difícil de cuantificar.

3.21.2010

Como hacer un demonio en python

Siempre llega ese día en el que necesitas tener un demonio funcionando en una máquina. Y cuando llegas ves que necesitas hacer un par de forks, cosas con stdin y stdout... un peñazo, por suerte en python existe una librería llamada python-daemon, aunque no está demasiado bien documentada (hay que bucear un poco en los fuentes), es muy útil para no tener que liarte demasiado para hacer el demonio. Aquí demo un ejemplo de uso de python-daemon con su log y sus redirecciones de los std*.

Para ejecutar el demonio se usa el interfaz típico de start|stop|restart, por ejemplo:
$ python daemon.py start



3.03.2010

Consejos para trabajar con python

Cada lenguaje tiene sus herramientas, su forma de trabajar, sus reglas de estilo, etc... aparte cada uno tenemos nuestros pequeños trucos y reglas para trabajar lo más ordenado posible. Por ello voy a dar una serie de consejos que he ido aprendiendo a medida que he ido programando en python que espero puedan ser de utilidad a otras personas que así lo hagan.

- Sigue las reglas de python. Para conocerlas basta con que ejecutes python -c "import this" en la consola. No son específicas python, creo que sirven para cualquier lenguaje, muy recomendable "lectura".

- Trata de seguir las recomendaciones de la guía de estilo del PEP-008 (Style Guide for Python Code). Los PEP (Python Enhancement Proposals) son documentos que se redactan y siguen cuando se implementa una nueva característica.

- Aprovecha la potencia del lenguaje. Si sabes ruby o similar sabrás de lo que hablo, los que vienen de java, C, C++ están acostumbrados a lenguajes más bien estáticos, se usa poco la metaprogramación. Python tiene cosas muy interesantes, por ejemplo las list comprehesions que agilizan mucho el desarrollo. Siempre con mucho cuidado de no pasarse (la gente de ruby me entenderá). Por ejemplo, la gente que viene de java suele escribir interfaces y luego heredar para a implementación. En python directamente usa duck typing.

- Cuidado con los imports. Salvo que sepas lo que haces trata de no hacer "from module import *". Primero porque si lo haces posiblemente es que no sepas ni lo que quieres usar, segundo porque puede ser una fuente de bugs importante. Es mejor hacer "from module import MyClass, MyClass2". A mi me gusta primero poner los imports de la librería estandard y después lo propios de la aplicación, pero es algo personal.

- Unicode: siempre especifica la codificación del fichero, en el pep-0263 tienes toda la información, pero el resumen es, pon la siguiente cabecera:

#!/usr/bin/python
# -*- coding: -*-

Si no lo haces tarde o temprano tendrás alguna excepción al ejecutar tu código por haber puesto caracteres fuera del ascii. Además, trata de entender como qué es unicode, como se hace para usarlo en python.

- Excepciones. No captures una excepción y no hagas nada. La gente que programa en java lo puede hacer (y de hecho lo hace), pero si eres un hombre de bien haz algo. Captura la excepción que corresponde, esto es, si esperas un socket.error no pongas un except que recoja a troche y moche, solo captura esa excepción.

- Las doctest son una verdadera virguería para documentar a la vez que testear. No en todos los sitios se pueden usar, pero por ejemplo si al comienzo de un módulo pones una explicación usando doctest mejorará bastante, por ejemplo:


"""
Este módulo sirve para sumar 3 números usando la función add3.
Un ejemplo de uso es:
>>> add3(1,2,3)
6
""""
def add3(....


Luego desde la consola puedes hacer:

python -m doctest modulo.py


y ver si algo casca. Más información de doctest y ejemplos. Además luego hay el módulo unittest, hay frameworks para stubs y mocks, helpers para facilitar los test como nose y pytest, todo lo necesario para estar a la última moda del TDD.

- usa la consola. Unas de las cosas más útiles es que tienes la consola siempre a mano para probar cosillas. La mayoría de las veces no me acuerdo como hacer algo, en la consola lo pruebas instantaneamente. Recomiendo usar ipython, que viene ser igual que la consola original python, pero con facilidades para acceder a la documentación, autocompletado, etc.

- Usar pip o easy_install. Es similar a gem en ruby, lo que hace es instalar módulos de terceros desde internet con un solo comando. Esto es fundamental y agiliza el desarrollo muchísimo. Para buscar el software usa Python Package Index donde tú mismo puedes subir tus paquetes. De hecho el paquete de la librería standard para empaquetar módulos lo sube automáticamente con un comando. Prefiero pip a easy_install porque pip está construído con más lógica (tiene uninstall) y más características que cuento dos puntos más abajo.

- Haz pequeños módulos y empaqueta. Empaquetar es súmamente sencillo, con hacer un fichero setup.py con pocos parámetros tienes el empaquetado hecho. Aparte de los benficios que tiene separar las aplicaciones en modulos, tiene otros muy interesantes. El módulo que se usa para estas cosas es distutils, donda hay un ejemplo de setup.py muy sencillo.

- Usa pip. Sí, es repetido, pero pongamos que tienes el caso que has separado tu aplicación en varios módulos que tienes en un repositorio. Desarrollas una aplicación que los necesita, pip te va a ayudar a resolver este problema ya que puede instalar módulos directamente del repositorio (siemre que tengan su setup.py), por ejemplo:


pip install svn+https://mirepo/project/module#egg=module


Todos los paquetes necesarios se pueden poner en un fichero requirements.txt que todas las aplicaciones tengan.

- virtualenv. Herramienta fundamental, permite aislar entornos de ejecución. Puedes crear tantos entornos como quieras, cada uno con una versión de python diferente, cada uno con sus librerías. Esta herramienta es, repito, fundamental. Yo lo uso junto a virtualenvwrapper que simplifica la creación y gestión de entornos. Además junto con pip hacen el combo perfecto. Por ejemplo, para tener un entorno de trabajo funcionando basta con hacer:


pip install -E env -r requirements.txt

pip creará un entorno nuevo, e instalará todo los especificado en el fichero requirements.txt, bajándose lo necesario. Luego basta con activar el entorno y a trabajar:


. ./env/bin/activate


- Aprender a usar el debugger, pdb. Sé que ya no mola hacer debug en la línea de comando, que eclipse te lo da todo mascadito, pero si estás en un servidor remoto es útil cuando solo tienes ssh y vim :).

- Usa el log. Python tiene un módulo llamado logging, úsalo, luego se puede configurar para redireccionar a un fichero, al syslog, a stdout. Tiene las típicas error, info, debug... pero lo importante es que lo uses.

En general, cuando no sé la mejor forma de hacer algo, suelo ir al código de la librería standard y mirar paquetes que suelo usar.