Mariano Draghi (cHagHi): De Tastil a León

Dar una vuelta por algún lugar de nuestro bellísimo NOA es mágico. Siempre. No importa cuantas veces lo haga, creo que no voy a cansarme nunca.

capilla

Capilla

Esta vez la aventura arrancó en Tastil, Salta, y terminó en León, Jujuy. Hermoso trekking. Kilómetros y kilómetros de puna, de la nada misma, de montaña y sol. A diferencia de otros recorridos, este transcurre al principio por caminos que ya ni los pocos pobladores que quedan usan, por zonas en donde no hay pueblitos, y miráramos para donde miráramos, estábamos solos con los paisajes que nos regalaba la Pacha.

Quizás por eso, quizás porque necesitaba estas vacaciones más que otras veces, quizás por tener la suerte de poder compartir la experiencia con un montón de amigos, probablemente por todo eso junto, fue una semana muy especial.

Me llevo un montón de cosas. La escuelita en la que paramos la primer noche y la hospitalidad de las maestras. Los alucinantes cielos estrellados a más de 3000 de altura y kilómetros de la civilización. La garra y la buena onda y las ganas de pasarla de diez a pesar del apunamiento que nos pegamos más de uno. La experiencia y hospitalidad de Nicanor. Emilia jugando a tirar piedritas con Ceci. Las anécdotas de Alberto. El corderito que pasó de su corral a nuestro plato en una tarde. La cumbre en el Picacho. El Chañi, que estuvo casi siempre ahí, y que cada día que pasaba parecía decir más fuerte "dale, vení alguna otra vez a subirme". Las risas. La amistad. El mate roto del Gordo, y sus pilas a pesar de que esta era su tercer travesía al hilo. La magia de Hielo Azul Aventura para juntar todas las piezas y que esta travesía haya sido posible.

https://farm4.staticflickr.com/3906/14633570650_5394847872.jpg

Me llevo otro poquito de NOA, y me voy contento.

Todas las fotos, acá: Tastil - León 2014.

Mariano Draghi (cHagHi): De Tastil a León

Dar una vuelta por algún lugar de nuestro bellísimo NOA es mágico. Siempre. No importa cuantas veces lo haga, creo que no voy a cansarme nunca.

Capilla
Capilla

Esta vez la aventura arrancó en Tastil, Salta, y terminó en León, Jujuy. Hermoso trekking. Kilómetros y kilómetros de puna, de la nada misma, de montaña y sol. A diferencia de otros recorridos, este transcurre al principio por caminos que ya ni los pocos pobladores que quedan usan, por zonas en donde no hay pueblitos, y miráramos para donde miráramos, estábamos solos con los paisajes que nos regalaba la Pacha.

Quizás por eso, quizás porque necesitaba estas vacaciones más que otras veces, quizás por tener la suerte de poder compartir la experiencia con un montón de amigos, probablemente por todo eso junto, fue una semana muy especial.

Me llevo un montón de cosas. La escuelita en la que paramos la primer noche y la hospitalidad de las maestras. Los alucinantes cielos estrellados a más de 3000 de altura y kilómetros de la civilización. La garra y la buena onda y las ganas de pasarla de diez a pesar del apunamiento que nos pegamos más de uno. La experiencia y hospitalidad de Nicanor. Emilia jugando a tirar piedritas con Ceci. Las anécdotas de Alberto. El corderito que pasó de su corral a nuestro plato en una tarde. La cumbre en el Picacho. El Chañi, que estuvo casi siempre ahí, y que cada día que pasaba parecía decir más fuerte “dale, vení alguna otra vez a subirme”. Las risas. La amistad. El mate roto del Gordo, y sus pilas a pesar de que esta era su tercer travesía al hilo. La magia de Hielo Azul Aventura para juntar todas las piezas y que esta travesía haya sido posible.

Me llevo otro poquito de NOA, y me voy contento.

Todas las fotos, acá: Tastil – León 2014.

Alejandro Santos: Eclipse Luna on Debian Wheezy Crash


The crash is related to a version mismatch between GTK2, GTK3 and Debian's GLIBC. The relevant bug is here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=430736

To force the use of GTK2 on Eclipse Luna you can try:
$ export SWT_GTK3=0
For a more permanent solution you can set the GTK version on the eclipse.ini file:
 --launcher.GTK_version
2
This option should be inserted before the --launcher.appendVmargs option.

And now you should be able to use Eclipse Luna on Wheezy.

Hernán Grecco: PyVISA 1.5 is out

PyVISA is a Python wrapper for the VISA library that enables controlling all kinds of measurement equipment through GPIB, RS232, USB and Ethernet. It has served the instrumentation community very well since 2005 (that's Python 2.3!) and still does.

However, Python and the different supported platforms have changed a lot in the recent years. We thought that PyVISA could use an update. Within the Lantz Project we did a small proof of principle of such update in visalib. Now we are taking what worked well and use it into PyVISA 1.5 (without changing the API!). In other words, PyVISA 1.5 brings several important changes in the underlying architecture without forcing you to change the programs.

Some time ago I posted that we were going beta. Now PyVISA 1.5 is finally released.

The new architecture is summarized here and the comparison with the previous one is here. Briefly you get Python 3 support, Mac OS X support, a better way to find libraries in your platform, an isolated ctypes wrapper. But the most important change is that the VISA library is not opened on import anymore. You can still use the instrument and get_instruments_list helpers (although we encourage not to do it!), but under the hood they will only instantiate a VisaLibrary object when you need them. We think that this will lead to more explicit and clear code, easier to deploy and to upgrade. There other small goodies around. Take a look at the docs.

You can install PyVISA or upgrade your previous version using pip:
 
$ pip install -U pyvisa

This release is only possible thanks to the contribution of a lot of people that contributed bug reports, testing and code. Thanks to everybody!

We are moving forward to make PyVISA even better. Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Read the docs: http://pyvisa.readthedocs.org/
or fork the code: https:/https://github.com/hgrecco/pyvisa/

Gabriel Patiño: Mapas topograficos propios

Hace un tiempo había subido unos mapas topográficos que hice a otro blog, pero se cayó el servicio donde estaban, asi que los pongo de nuevo, esta vez en un server propio.

Los mapas son imagenes diseñadas para imprimir en tamaño A3. Pueden mandar a imprimirlos a una imprenta o imprimirlo en dos A4 y pegarlas.

Va la lista de mapas que tengo por el momento:



La verdad que estaba bueno hacer esto, deberia volver a hacer algunos de la zona (SMA).

Martín Gaitán: Deploy de Django con Circus, Chaussette y Nginx

Aunque hay un pequeño mito al respecto, poner en producción una aplicación web hecha en Python no es tan complejo. Esa facilidad se debe a la estandarización de la pasarela WSGI, que define cómo se comunica (o se debería comunicar) una "app" (sea hecha con un framework o no) con un servidor web.

Si bien Nginx, el servidor web que está desplazando a Apache como el más popular tiene un módulo que implementa el estándar WSGI de manera nativa, la arquitectura más típica es utilizarlo como proxy reverso, conectado a un servidor WSGI especializado como Gunicorn que interactua con la aplicación web (posiblemente a través de multiples instancias o workers). Como queremos que nuestra app funcione permanentemente, el proceso WSGI y otros que sean necesarios (por ejemplo Redis) se demonizan de manera que sepan restaurarse automáticamente si mueren y sea posible monitorearlos: para eso suele usarse supervisor.

https://raw.githubusercontent.com/mozilla-services/circus/dff6cf3a348fecc0b58bd08cae91b1508aed14c2/docs/source/classical-stack.png

La arquitectura de deployment más común para una aplicación web Python

Si bien esta arquitectura está bastamente probada, hay una opción mejor.

https://circus.readthedocs.org/en/0.11.1/_images/circus-medium.png

El circo y el soquete

Circus y Chaussette son proyectos desarrollados por Tarek Ziadé y el equipo de Mozilla Sevices.

Consejo

Tarek es un pythonista francés, core committer de Python y muchos proyectos relacionados. Recibió el reconocimiento de la PSF por sus aportes y es autor del gran libro Expert Python Programming

Una arquitectura de producción análoga a la descripta arriba, pero basada en Circus, se ve así:

https://raw.githubusercontent.com/mozilla-services/circus/dff6cf3a348fecc0b58bd08cae91b1508aed14c2/docs/source/circus-stack.png

Circus maneja procesos demonizados igual que Supervisor, pero además puede bindear sockets y manejarlos de la misma manera. Este desacople de la gestión de sockets del webserver WSGI permite muchas posibilidades, tanto en la gestión como en la escalabilidad de la arquitectura.

La capa WSGI en este esquema la aporta Chaussette, que tiene la particularidad que, en vez de abrir un socket nuevo, utiliza el que Circus abrió (y controla) para el worker. Además, aunque trae una implementación de WSGI built-in, puede usar muchos backends más eficientes o con características particulares como meinheld, gevent, gevent-socketio, entre muchos otros.

A diferencia de Supervisor que se basa en el protocolo XML-RPC para inspeccionar los procesos que controla, Circus utiliza un canal pub/sub basado en el mucho más moderno ZeroMQ (lo mismo que usa IPython Notebook) que permite un monitoreo realtime y una API de plugins mucho más simple. Otra diferencia, nada menor, es que Circus funciona con Python 2 o 3 (supervisor no es compatible con Python 3).

Y de yapa: Circus se puede usar como una biblioteca de muy alto nivel para la gestión no bloqueante de procesos. Se puede pensar con un wrapper de subprocess y/o multiprocess, que aporta información de monitoreo y estadísticas, control de flujo, una capa de señales (hooks) muy completa y más.

Desplegando Django

Para ejemplificar, voy utilizar un proyecto Django que estoy desarrollando (muy lentamente): nikolahub.

Circus se configura con un archivo con formato .ini. El mio, que bauticé circus.ini quedó así:

[circus]
check_delay = 5
endpoint = tcp://127.0.0.1:5555
pubsub_endpoint = tcp://127.0.0.1:5556
stats_endpoint = tcp://127.0.0.1:5557

[socket:nikolahub]
host = 127.0.0.1
port = 8080

[watcher:nikolahub]
cmd = /virtualenvs/nikolahub/bin/chaussette --fd $(circus.sockets.nikolahub) nikolahub.wsgi.application
use_sockets = True
numprocesses = 3

[env:nikolahub]
PYTHONPATH = /projects/nikolahub

La sección watcher indica lanza el comando a controlar, en este caso levantando 3 workers de la aplicación -django. Notar que como tengo instalado Chaussette dentro del virtualenv, uso el path absoluto al ejecutable. El fragmento --fd $(circus.sockets.nikolahub) se expande implícitamente asignando el pid que obtuvo el fork (el proceso hijo) de circus.

Si quisieramos usar otro servidor web, sólo hay que indicar cual con el parámetro --backend Por ejemplo:

cmd = /virtualenvs/nikolahub/bin/chaussette --backend gevent --fd $(circus.sockets.nikolahub) nikolahub.wsgi.application

Podemos probar si todo funciona:

(nikolahub)tin@morochita:$ circusd circus.ini
2014-06-12 04:36:16 circus[1141] [INFO] Starting master on pid 1141
2014-06-12 04:36:16 circus[1141] [INFO] sockets started
2014-06-12 04:36:16 circus[1141] [INFO] Arbiter now waiting for commands
2014-06-12 04:36:16 circus[1141] [INFO] nikolahub started
2014-06-12 04:36:16 circus[1141] [INFO] circusd-stats started
2014-06-12 04:36:17 circus[1150] [INFO] Starting the stats streamer
2014-06-12 04:36:17 [1149] [INFO] Application is <django.core.handlers.wsgi.WSGIHandler object at 0xa06f60c>
2014-06-12 04:36:17 [1149] [INFO] Serving on fd://5
2014-06-12 04:36:17 [1149] [INFO] Using <class chaussette.backend._wsgiref.ChaussetteServer at 0x9f2d6ec> as a backend
2014-06-12 04:36:17 [1148] [INFO] Application is <django.core.handlers.wsgi.WSGIHandler object at 0x939b60c>
2014-06-12 04:36:17 [1148] [INFO] Serving on fd://5
2014-06-12 04:36:17 [1148] [INFO] Using <class chaussette.backend._wsgiref.ChaussetteServer at 0x92596ec> as a backend

Tendremos la aplicación servida en el puerto 8080 de localhost. Demonizarlo es sólo un flag:

(nikolahub)tin@morochita:$ circud --daemon circus.ini

Para implementar nginx como proxy reverso armé un archivo nginx.conf:

server {
    listen 80;
    server_name nikolahub.nqnwebs.com;

    location /static/ {
            alias /projects/nikolahub/static/;
    }

    location /media/ {
        alias /projects/nikolahub/media/;
    }

    location / {
        proxy_pass http://localhost:8080/;
        proxy_pass_header Server;
        proxy_set_header Host $host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 600;
        proxy_send_timeout 600;
        proxy_read_timeout 600;
    }
}

Luego agregamos el sitio:

$ ln -s /etc/nginx/sites-available/nikolahub nginx.conf
$ ln -s /etc/nginx/sites-enable/nikolahub nginx.conf
$ sudo service nginx restart
http://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Reverse_proxy_h2g2bob.svg/400px-Reverse_proxy_h2g2bob.svg.png

Esto pone a nginx como "frontend" de la aplicación, sirviendo los directorios con contenido estático y pasando el resto de las peticiones al puerto 8080 que administra Circus.

Ya tenemos nuestro sitio en producción.

El dueño del circo y los monitos

De ahora en más, podremos usar las herramientas que provee Circus.

circusctl es el dueño del circo. Puede parar, reiniciar, cambiar la cantidad de workers, abrir una consola ipython para interactuar o inspeccionar y mucho mas. Se puede usar como subcomandos (circusctl <subcmd> <watcher>) o usar la consola interactiva.

Por ejemplo, si quisiera ver cuantos procesos workers tengo y agregar uno más, podría hacer así:

(nikolahub)tin@morochita:$ circusctl numprocesses nikolahub
3
(nikolahub)tin@morochita:$ circusctl incr nikolahub
ok
(nikolahub)tin@morochita:$ circusctl numprocesses nikolahub
4

Lo mismo y más se puede hacer desde una consola IPython.

(nikolahub)tin@morochita:$ circusctl ipython
Python 2.7.4 (default, Apr 19 2013, 18:32:33)
Type "copyright", "credits" or "license" for more information.

IPython 2.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: arbiter.numprocesses()
Out[1]: 4

circus-top es un monitor realtime, estilo top. Escucha las estadísticas que produce circusd-stats.

(nikolahub)tin@morochita:$ circus-top
/images/circus-top.png

circus-top en acción. Muestra los procesos watcher y los recursos que cosumen.

Todo esto puede verse y manejarse cómodamente a través de circus-web, un dashboard web que permite monitorear y administrar circus, con gráficos realtime y muy fácil de usar.

https://circus.readthedocs.org/en/0.11.1/_images/web-watchers.png

Desde las últimas versiones, circus-web se refactorizó para basarla en Tornado (originalmente usaba bottle) y hay que instalarlo aparte.

$ pip install circus-web

Conclusiones

Circus es una herramienta que simplifica el stack de deployment de una aplicación web WSGI. La API de alto nivel, una arquitectura mucho más moderna y simple y el aval de ser desarrollada (y usada exhaustivamente) por Mozilla, son avales poderosos para probarla.

Como escribió el Marcos Luc "la función ya debería empezar (...) Bueno nena, buena suerte, cada vez la red te teme más..."

Marcos Dione: optimizing-mapnik-rendering-with-metatiles

One of the most cited ways to accelerate rendering maps with Mapnik is metatiling. This technique is simple: instead of rendering each individual 256x256 PNG file that normally backs a slippy map, render NxN times that (normally with N=8) and split afterwards. mapnik-stylesheet's generate_tiles.py was not capable of doing it, but I hacked a little bit and got it to do it, so after integrating openstreetmap-carto v2.14.1 and fixing some local bugs, I gave it another spin.

This time I also imported the whole Europe data, and expanded the terrain to cover anything above 60°N, taking the height files form De Ferranti's viewfinderpanoramas. This meant that whatever rendering times I got this time, they are not completely comparable to what I obtained before because it's simply handling way more data, specially relative to the terrain data.

So, first, a short revisit to importing. Here's the summary:

mdione@diablo:/var/lib/data/mdione/src/projects/osm/data/osm$ osm2pgsql \
    --create --drop --database gis --slim --flat-nodes /home/mdione/src/projects/osm/nodes.cache \
    --cache 2048 --number-processes 4 --unlogged europe-latest.osm.pbf
osm2pgsql SVN version 0.82.0 (64bit id space)

Node-cache: cache=2048MB, maxblocks=262145*8192, allocation method=11
Mid: loading persistent node cache from /home/mdione/src/projects/osm/nodes.cache
Allocated space for persistent node cache file
Maximum node in persistent node cache: 0
Mid: pgsql, scale=100 cache=2048

Reading in file: europe-latest.osm.pbf
Processing: Node(1225816k 799.6k/s) Way(151242k 17.71k/s) Relation(1872470 338.91/s)  parse time: 15596s [4h20m]
Node stats: total(1225816996), max(2884224404) in 1533s [0h26m]
Way stats: total(151242682), max(284701738) in 8538s [2h22m]
Relation stats: total(1872475), max(3776697) in 5525s [1h32m]

Going over pending ways...
Maximum node in persistent node cache: 2884632575
        110980610 ways are pending
Using 4 helper-processes [but only 1 is used, the others failed, dunno why]
Mid: loading persistent node cache from /home/mdione/src/projects/osm/nodes.cache
Maximum node in persistent node cache: 2884632575
Process 0 finished processing 110980610 ways in 34202 sec [9h30m]
110980610 Pending ways took 34202s at a rate of 3244.86/s

Going over pending relations...
Maximum node in persistent node cache: 2884632575
        0 relations are pending
Using 4 helper-processes
Process 2 finished processing 0 relations in 2 sec
Process 3 finished processing 0 relations in 2 sec
Process 0 finished processing 0 relations in 3 sec
Process 1 finished processing 0 relations in 3 sec
0 Pending relations took 3s at a rate of 0.00/s

node cache: stored: 203128264(16.57%), storage efficiency: 75.67% (dense blocks: 138131, sparse nodes: 63494657), hit rate: 17.62%

Stopped table: planet_osm_rels in 1s
Stopped table: planet_osm_nodes in 1s
Stopped table: planet_osm_ways in 3s

All indexes on  planet_osm_roads created  in 4679s [1h18m]
All indexes on  planet_osm_point created  in 6093s [1h41m]
All indexes on  planet_osm_line created  in 9703s [2h42m]
All indexes on  planet_osm_polygon created  in 12735s [3h32m]

Osm2pgsql took 62780s overall [17h26m]

Only ~3h30m more than importing a part of Europe, I think it's manageable. I still don't know what to make out of the cache/storage efficiency line, but it's clearly related to the small size of the cache.

About the rendering, I only rendered up to zoom level 11, as I discussed before, but that limit was mostly due to the fact that going all the way down to 14 took too much time. But after viewing how much less rendering took this time, I most probably revert that change. Take a look at the graph:

This graph shows the average and total time for rendering up to zoom level 11 with single tiling (actually it's the old data I showed previously) and metatiling 8x8. The total time uses the logarithmic scale on the right. The average in the second case is the division between the total time and the amount of final individual tiles, which are produced by cutting the metatile in as many single tiles as the minimum between 2^z and 64, so zoom levels 0-2 don't produce spurious images. The times are amazing. Notice that from time to time the total time took more in the metatile version than in the single tile version, but the are two factors that impact here. One is that due to metatiling, I'm rendering tiles that with single tiling I wouldn't due to the fact that now I can only cut in increments of 8 instead of one. Two, now I'm rendering the whole Europe instead of just a big part of it. This makes the amount of tiles produced to be between 6 to 10 times more.

Still, take a look at the average rendering times for metatiling, and specially at the last column in the table, which is not graphed: it's the proportion between the average tile rendering time, meta to single. It's mostly below the 10%, except for a couple of zoom levels that either produce few tiles (ZL 2, 16 tiles) or stay under 15% (ZL 4). This is ridiculously low, which means fast. I will first finish rendering my zone down to ZL 18 and then render the rest down to ZL 14 to have more complete, comparable graphs.


openstreetmap gis