Juanjo Conti: 1er meetup de Python en Santa Fe

   Publicado:

Cómo surgió

Durante 2006, 2007 y 2008 se llevaron a cabo en la UTN de la ciudad de Santa Fe tres eventos denominados "Python en Santa Fe".

Para muchas personas de la ciudad y alrededores fue su primer contacto con el lenguaje, incluso con la programación.

Luego de eso, las actividades relacionadas con Python llevadas a cabo por porsonas de la ciudad se fueron canalizando a travéz de PyAr, el grupo de usuarios de Python Argentina y si bien nos encontrábamos en eventos a nivel nacional en distintos puntos del país (PyCons, PyCamps, PyDays) casi no nos volvimos a juntar.

El año pasado se empezó a usar mucho la plataforma de meetup.com en la ciudad (hay por ejemplode Ruby, de JavaScript, de Postgres...). Lo que me gusta del esta es que te permite descubrir comunidades que no conocías y que se reúnen en tu misma ciudad (lo que implica conocer nuevas personas, proyectos, etc...).

Fue por eso que hace un par de meses, sin muchas expectativas, cree el Meetup de Python en Santa Fe. Rápidamente llegamos al límite del plan gratuito de 50 miembros y pedí ayuda a la Python Software Foundation para tener una cuenta paga. Luego de aceptar las solicitudes pendientes llegamos a 66 pythonistas en Santa Fe y ya no pude huir del peso del deber: le puse fecha a nuestro primer evento. Uno de los asistentes se encargó de hablar con la gente de un bar y todo estuvo listo.

La idea del primer meetup fue entonces un encuentro social, sin charlas ni slides.

La meetup en sí

La meetup fue muy distinta a lo que me había imaginado que sería.

Habían confirmado unas 17 personas. A muchas de ellas no las conocía. Pensé encontrarme con muchos programadores Python. ¿Podría ser posible esto? ¿Gente que no esté en la lista de PyAr? ¡Hasta había preparado una pequeña encuesta!

No fue así.

  • Más de la mitad faltó sin avisar.
  • De los programadores que fueron, los conocía a todos.
  • Fue gente que sabía poco de programación, pero estaba muy entuciasmada en participar.

Esto último fue lo mejor. Hablamos de dos temas principalmente y de cómo podíamos ayudar con Python. Uno fue arte digital y el otro el banco de alimentos que se está por abrir en la ciudad.

Tal vez pronto surgan novedades de alguna actividad interdiciplinaria relacionado a estos temas.

PyConAr

En un momento de la meetup fuimos intervenidos :) Llegaron tres miembros de la cooperativa Coprinf y nos contaron sobre la organización que se está llevando a cabo para la próxima PyConAr que va a ser en Bahía Blanca y está organizada por un conjunto de cooperativas.

Nos contaron que la idea es que este año el foco esté en la comunidad (en contraste a la anterior que se sintió demasiado empresarial) y en esta línea una de las ideas es que haya un colectivo que salga del norte, pase por varios lugares donde haya comunidades (incluído Santa Fe) y llegue hasta Bahía Blanca.

Se quedaron casi una hora y estuvo re bueno que pasen.

El lugar

Un apartado especial para el lugar.

La música estaba un poco más fuerte de lo deseado y hasta toco una banda. Tenías que arrimarte para escuchar lo que estaban diciendo en la otra punta de la mesa.

Las luces y la ambientación estaban buenas. Nos gustaron unas pinturas en las paredes que cambiaban de color con la luz e incluso vimos cuando las seguían pintando en vivo.

Como nota de colar, la pizzeada no fue tal ya que el bar se había quedado sin pizzas. Nos trajeron unas picadas que si bien estuvieron ricas, terminaron costando un poco más que el precio que nos habían dado para la "pizza libre".

Facundo Batista: Ordenando fotos

   Publicado:


Hace un par de semanas sucediose el PyCamp. En este tipo de eventos, como en tantos otros, o paseos, o reuniones, o lo que sea, pasa que uno lleva "la cámara", pero no la usa todo el tiempo.

Con "la cámara" me refiero al dispositivo para sacar fotos de mejor calidad que uno tiene. Puede ser una reflex toda pipona, o una point and shoot berretona, o algo intermedio (o "bridge") como la que tengo yo (una Canon G15).

Canon G15

Y uno no la usa todo el tiempo por dos razones. La primera es que en general, a menos que sea una point and shoot finiiiiita, molesta un poco llevarla: te ocupa al menos una mano, o rellena bastante un bolsillo, o hay que llevarla al cuello, o hay que llevar todo un bolso al hombro.

La segunda razón es que como las cámaras en los teléfonos avanzaron bastante, uno siempre termina sacando fotos al voleo más con el celular que con otra cosa, y deja para momentos "más cuidados" el usar "la cámara".

Y me pasa todo el tiempo. Ejemplo típico del del PyCamp: tengo la cámara en la mochila, donde la guardé luego de sacar un par de fotos donde estábamos trabajando, pero luego fui a otro lado a preguntarle algo a alguien, y tuve ganas de sacar una determinada foto, y en el momento lo resolví con el teléfono. No iba a volver a buscar la cámara grande. O la sacaba con el teléfono, o no la sacaba.

Entonces, esta combinación de factores hizo que, en los últimos tiempos, termine con una serie de fotos de la cámara grande, más una serie de fotos del teléfono. Separadas.

Yo miro/edito las fotos con distintas herramientas. Pero en general, las veo ordenadas por el nombre del archivo. Entonces, tener dos series de fotos separadas me jodía bastante.

Es por eso que me armé un pequeño script que agarra todas las fotos de un directorio y las renombra en función de la fecha/hora que tiene guardada la foto, quedando ambas series efectivamente mezcladas de forma cronológica al ordenarlas por el nombre del archivo.

Un par de detalles con respecto al script.

  • Todavía está en desarrollo, pero está bastante estable y las últimas veces que lo usé anduvo 100% ok
  • Asume que las fotos de "la cámara" tienen el formato IMG99999.JPG, siendo los 99999 cinco dígitos cualesquiera. Si este no es tu caso, vas a tener que pedirme una mejora, o toquetear vos misma/o el código.
  • Tenés que tener fades instalado, para que te maneje automágicamente las dependencias (acá tenés una explicación al respecto). Si no querés instalar fades, arreglate.

Enjoy.

Facundo Batista: PyCamp 2016

   Publicado:


Durante este finde largo de semana santa hicimos la edición 2016 del PyCamp, el que para mí es el mejor evento del año.

Se realizó nuevamente en La Serranita, un lugar muy lindo y muy cómodo, el Complejo Soles Blancos. A diferencia del año pasado, que fue en Agosto, esta vez a la noche sólo estuvo bastante fresco, :). Las tardes eran con un lindo calorcito, y las noches y madrugadas estaban fresconas, ideal para pasear por la calle o dormir!

Como la vez pasada, hice Buenos Aires - Córdoba (Capital) en micro, y de ahí a La Serranita en auto (a la vuelta lo mismo). Es más, el trayecto de ida lo manejé yo (porque Pancho estaba rotazo), y la vuelta la hizo él, con lo que pude disfrutar más del paisaje.

Alta vista

Como todos los PyCamps, este se dividió mucho entre lo que es Python propiamente dicho, y lo que son otras actividades. Arranquemos con lo que es programación propiamente dicho.

El proyecto más largo en el que participé fue un Tower Defense: el típico jueguito donde uno ubica torres que atacan un flujo de enemigos que se vienen encima, y en función de la habilidad de colocar qué torres y dónde, uno se defiende mejor o peor. La idea era no sólo diseñar y armar el juego, sino también crear una inteligencia artificial que aprendiera a ubicar las torres.

En esto se anotaron casi todos, así que fue con lo primero que arrancamos. Lo más interesante fue la organización. En seguida separamos lo que es "core" de la "ai", y un grupo se quedó arriba y otro nos fuimos para la sala de abajo. No sé bien qué hicieron los de AI, arriba, pero abajo armamos entre todos la estructura básica del core, nos separamos en pequeños grupos, y atacamos todo el código en paralelo, charlando las interfaces/APIs a medida que íbamos agregando o solucionando cosas.

Fue genial. El primer día ya teníamos como un 80% de lo que logramos finalmente, y luego seguimos trabajando. El producto fue un core a todo lujo, con gráficos y todo (usamos pyglet), más una inteligencia artificial que aprendía eficientemente a ubicar las torres. Impecable.

Screenshot del TD

De los proyectos que llevaba yo, en el que más se enganchó la gente fue fades. Como con Nico tenemos los issues bien claritos y clasificados, los chicos encontraban enseguida algo para hacer. Metimos varios fixes y cerramos muchos issues, se avanzó bastante. También se anotaron varios para trabajar en la web de PyAr, se avanzó un poco, sobre problemas de formateo y links rotos (porque no existen, pero también porque apuntan mal internamente en el wiki). No hicimos tanto, quedó pendiente para seguir en otro momento. También otro grupo (principalmente Matu Varela, Mati Barrientos y Toni) estuvieron con la integración del sitio de PyAr y unos bots de Telegram, que originalmente estaban planeados para desparramar info, pero sobre los cuales luego armaron esquemas de moderación de noticias, eventos y trabajos postulados.

Con otros proyectos estuve también bastante tiempo, pero con menos gente. Para Linkode estuvimos charlando mucho con Mati Barrientos y Pablo Celayes, sobre los próximos planes a nivel de interfaz. Decidimos ir a algo como una "single page application" pero que apenas es tal, porque la interfaz de linkode es muy sencilla. Así y todo, la idea es que el "cliente web" use la API de linkode como cualquier otro cliente. Más allá de toda la charla y la decisión de cómo seguir para adelante, Matías va a estar liderando todo el lado "javascript" de linkode, metiendo código él y revisando/empujando el de otros.

Gente trabajando

Para cerrar todo lo hecho, y el PyCamp en sí, hicimos un video! Jose Luis Zanotti tiene pendiente de editarlo y armarlo, así mostramos todo lo que hicimos en un par de días...

Y por otro lado, hubieron varias actividades no relacionadas directamente con programar en Python.

El más centralizadamente coordinado fue un torneo de Tron, que ganó Jose Luis Zanotti Ya habíamos hecho algo parecido en el PyCamp de La Falda, hace varios años, y es notable como uno se engancha mirando a las personas que compiten y cómo juegan. También hubieron clases de sable, una tarde, y noches de juegos de mesa. Yo jugué dos veces al Resistance, un juego donde (aunque tiene soporte de fichas y tarjetitas) lo importante es la interacción entre las personas y como todos se tratan de convencer entre todos de que no son nazis.

La estrella de las actividades de "no programación" fue la reunión de PyAr (gracias Ariel por armar la minuta). Estuvo buenísima, por cuanto y cómo participaron todos. Charlamos de la próxima PyCon, de cómo venía el tema de la creación de la Asociación Civil, y también del PyCamp actual, y cosas que deberíamos mantener o mejorar. Luego de la reunión, un asadazo, que lo preparó (muy bien, como siempre), el anfitrión del complejo, Leandro.

En la reunión

Todas las fotos que saqué yo, acá.

Marcos Dione: ruby-cheatsheet-for-pythonistas

   Publicado:

In a shallow but long yak shaving streak, I ended up learning Ruby (again). Coming from a deep Python background (but also Perl and others), I sat to write down a cheatsheet so I can come back to it time and again:

module Foo  # this is the root of this namespace
# everything defined here must be referenced as Foo::thing, as in
Foo::CamelCase::real_method()

:symbol  # symbols are the simplest objects, wich only have a name and a unique value
:'symbol with spaces!'

"#{interpolated_expression}"  # how to iterpolate expressions in strings

/regular_expression/  # very Perl-ish

generator { |item| block }  # this is related to yield

%q{quote words}  # à la perl!
%w{words}  # same?

def classless_method_aka_function(default=:value)  # Ruby calls these methods too
    block  # ruby custom indents by 2!
end

method_call :without :parens

class CamelCase < SuperClass  # simple inheritance
    include Bar  # this is a mixin;
    # Bar is a module and the class 'inherits' all its 'methods'

    public :real_method, :assign_method=
    protected :mutator_method!
    private :query_method?

    self  # here is the class!
    def real_method(*args)  # splat argument, can be anywhere
        # no **kwargs?
        super  # this calls SuperClass::real_method(*args)
        # comapre with
        super()  # this calls SuperClass::real_method()!

        local_variable
        @instance_variable  # always private
        @@class_variable  # always private
        $global_variable

        return self
        # alternatively
        self
        # as the implicit return value is the last statement executed
        # and all statements produce a value
    end

    def assign_method=()
        # conventionally for this kind of syntactic sugar:
        # When the interpreter sees the message "name" followed by " =",
        # it automatically ignores the space before the equal sign
        # and reads the single message "name=" -
        # a call to the method whose name is name=
    end

    class << self
        # this is in metaclass context!
    end

    protected
    def mutator_method!(a, *more, b)
        # conventionally this modifies the instance
    end

    private
    def query_method?()
        # conventionally returns true/false
    end
end

# extending classes
class CamelCase  # do I need to respecify the inheritance here?
    def more_methods ()
    end
end

obj.send(:method_name_as_symbol, args, ...)

begin
    raise 'exceptions can be strings'
rescue OneType => e  # bind the exception to e
    # rescued
rescue AnotherType
    # also
ensure
    # finally
else
    # fallback
end

=begin
Long
comment
blocks!
=end

statement; statement

long \
line

# everything is true except
false
# and
nil

variable ||= default_value

`shell`

AConstant  # technically class names are constants
# so do module names
A_CONSTANT  # conventionally; always public
# The Ruby interpreter does not actually enforce the constancy of constants,
# but it does issue a warning if a program changes the value of a constant

# case is an expression
foo = case
    when true then 100
    when false then 200
    else 300
end

do |args; another_local_variable|
    # args are local variables of this block
    # whose scope ends with the block
    # and which can eclipse another variable of the same name
    # in the containing scope

    # another_local_variable is declared local but does not
    # consume parameters
end

{ |args| ... }  # another block, conventionally single lined

# Matz says that any method can be called with a block as an implicit argument.
# Inside the method, you can call the block using the yield keyword with a value.

# Matz is Joe Ruby

# yield is not what python does
# see http://rubylearning.com/satishtalim/ruby_blocks.html
# block_given?

a= []  # array
a[0] == nil

ENV  # hash holding envvars
ARGV  # array with CL arguments

(1..10)  # range
(0...10)  # python like
5 === (1..10)  # true, 'case equality operator'

{ :symbol => 'value' } == { symbol: 'value' }  # hashes, not blocks :)

lambda { ... }  # convert a block into a Proc object

# you cannot pass methods into other methods (but you can pass Procs into methods),
# and methods cannot return other methods (but they can return Procs).

load 'foo.rb'  # #include like
require 'foo'  # import, uses $:
require_relative 'bar'  # import from local dir

It's not complete; in particular, I didn't want to go into depth on what yield does (hint: not what does in Python). I hope it's useful to others. I strongly recommend to read this tutorial.

Also, brace yourselves; my impression is that Ruby is not as well documented as we're used in Python.


python

Marcos Dione: ayrton-0.7.2.1

   Publicado:

ayrton is an modification of the Python language that tries to make it look more like a shell programming language. It takes ideas already present in sh, adds a few functions for better emulating envvars, and provides a mechanism for (semi) transparent remote execution via ssh.

A small update on v0.7.2:

  • Fix iterating over the log ouput of a Command in synchronous mode (that is, not running in the _bg). This complements the fix in the previous release.

Get it on github or pypi!


python ayrton

Marcos Dione: ayrton-0.7.2

   Publicado:

This time we focused on making ayrton more debuggable and the scripts too. Featurewise, this release fixes a couple of bugs: one when executing remote code with the wrong Python version and another while iterating over long outputs. The latter needs more work so it's more automatic. Here's the ChangeLog:

  • Fix running remote tests with other versions of Python.
  • Fix tests broken by a change in ls's output.
  • Fix iterating over the long output of a command à la for line in foo(...): .... Currently you must add _bg=True to the execution options.
  • Fix recognizing names bound by for loops.
  • Added options -d|--debug, -dd|--debug2 and -ddd|--debug3 for enabling debug logs.
  • Added option -xxx|--trace-all for tracing all python execution. Use with caution, it generates lots of output.

Get it on github or pypi!


python ayrton

Marcos Dione: ayrton-0.7.1

   Publicado:

A weird release, written from Russia via ssh on a tablet. The changelog is enough to show what's new:

  • Iterable parameters to executables are expanded in situ, so foo(..., i, ...) is expanded to foo (..., i[0], i[1], ... and foo (..., k=i, ...) is expanded to foo (..., k=i[0], k=i[1], ....
  • -x|--trace allows for minimal execution tracing.
  • -xx|--trace-with-linenos allows for execution tracing that also prints the line number.

Get it on github or pypi!


python ayrton

Marcos Dione: trip-planner

   Publicado:

For a long time I've been searching for a program that would allow me to plan (car) trips with my friends. Yes, I know of the existence of Google Maps, but the service has several characteristics that doesn't make it appealing to me, and lacks a couple of features I expect. This is more or less the list of things I want:

  1. Define the list of points I want to go to. No-brainer.
  2. Define the specific route I want to take. This is normally implemented by adding more control points, but normally they're of the same category as the waypoins of the places you want to visit. I think they shouldn't.
  3. Define stages; for instance, one stage per day.
  4. Get the distance and time of each stage; this is important when visiting several cities, for having an idea of how much time during the day you'll spend going to the next one.
  5. Define alternative routes, just in case you don't really have/make the time to visit some points.
  6. Store the trips in cookies, share them via a URL or central site, but that anybody can easily install in their own server.
  7. Manage several trips at the same time.

So I sat down to try and create such a thing. Currently is just a mashup of several things GIS: my own OSM data rendering, my own waypoints-in-cookies idea (in fact, this is the expansion of what fired that post) and OSRM for the routing. As for the backend, I decided to try flask and flask-restful for creating a small REST API for storing all this. So far some basics work (points #1 and #6, partially), and I had some fun during the last week learning RESTful, some more Javascript (including LeafLet and some jQuery) and putting all this together. Here are some interesting things I found out:

  • RESTful is properly defined, but not for all URL/method pairs. In particular, given that I decide that trip ids are their name, I defined a POST to trips/ as the UPSERT for that name. I hope SQLAlchemy implements it soon.
  • Most of the magic of RESTful APIs happen in the model of your service.
  • Creating APIs with flask-restful could not be more obvious.
  • I still have to get my head around Javascript's prototypes.
  • Mouse/finger events are a nightmare in browsers. In particular, with current leafLet, you get clicked events on double clicks, unless you use the appropriate singleclick plugin from here.
  • Given XSS attacks, same-origin policy is enforced for AJAX requests. If you control the web service, the easiest way to go around it is CORS.
  • The only way to do such calls with jQuery is using the low level function $.ajax().
  • jQuery provides a function to parse JSON but not to serialize to it; use window.JSON.stringify().
  • Javascript's default parameters were not recognized by my browser :(.
  • OSRM's viaroute returns the coordinates multiplied by 10 for precision reasons, so you have to scale it down.
  • Nominatim and OSRM rock!

I still have lots of things to learn and finish, so stay tunned for updates. Currently the code resides in Elevation's code, but I'll split it in the future.

Update:

I have it running here. You can add waypoints by clicking in the map, delete them by doublecliking them, save to cookies or the server (for the moment it overwrites what's there, as you can't name the trips or manage several yet) and ask for the routing.

trip-planner elevation openstreetmap osrm python flask leaflet javascript jquery

Facundo Batista: Python y el manejo de dependencias

   Publicado:


(there is an English version of this post, here)

Python tiene una biblioteca estándar muy extensa ("viene con las pilas incluídas"), pero es frecuente la necesidad de usar otros módulos que están afuera de la misma, casi siempre desde el Índice de Paquetes de Python (PyPI).

La manera original de instalar esos módulos es a "nivel de sistema" (sudo pip install foobar), en el sistema operativo de forma general, habilitándolos para ser utilizados por cualquier programa que se ejecute.

Más allá de necesitar permisos de root o administrador para instalar las dependencias de esta manera, el primer problema con el que nos encontramos es el de conflictos: el caso típico de dos programas que necesitan la misma dependencia pero en versiones distintas, lo cual no puede lograrse al instalar las dependencias en forma global.

Por eso es que es tan normal en el mundo de Python usar "entornos virtuales". Se crea un entorno virtual para cada programa, se instala las dependencias necesarias para cada programa en cada entorno virtual, y como lo que instalamos en ese entorno es sólo accesible desde dentro del entorno, no hay más conflictos.

En este punto, sin embargo, aparece el problema de la administración de los entornos virtuales: crearlos, instalarles cosas, activarlos para usarlos con cada programa y desactivarlos luego, recordar los nombres de cada entorno para cada programa, etc.

Para automatizar esto nació fades.

fades les permite utilizar todo el poder de los entornos virtuales sin tener que preocuparse por ellos.

¿Quieren ejecutar un script que necesita la dependencia foobar?

    fades -d foobar script.py

¿Quieren un intérprete interactivo teniendo foobar instalado como dependencia?

    fades -d foobar

¿Necesitan ejecutar el script pero con varias dependencias, alguna en una versión específica?

    fades -d foo -d bar -d baz==1.1 script.py

¿Tienen todas las dependencias en un archivo de requerimientos?

    fades -r requirements.txt script.py

Esto es sólo lo más sencillo que podés hacer con fades. Los entornos virtuales son una herramienta poderosísima, y automatizar y simplificar su uso hace que fades tenga bastantes opciones, algunas que usarán todos los días, y otras que les van a resultar muy útiles en casos puntuales.

Empiecen a usar fades de a poco (acá tienen toda la documentación) y van a encontrar que van a tener resuelto el tema de la administración de dependencias en programas y scripts, usando entornos virtuales pero sin la complejidad de tener que hacerlo directamente y a mano.

Facundo Batista: Todo lo que siempre quisieron saber de la CDPedia y nunca se atrevieron a preguntar

   Publicado:


¿Qué es?

La CDPedia es la Wikipedia Offline. O sea, la Wikipedia, lo más fiel posible a su formato y contenido original, pero armada (construida, compactada) de una manera que no se necesita nada de Internet para acceder a toda la info de la misma.

Se llama CDPedia porque la idea original era meterla en un CD. Hoy por hoy generamos cuatro imágenes en cada liberación de CDPedia: un CD, un DVD, y dos archivos comprimidos (uno mediano y otro grande) que se pueden poner en un pendrive o en cualquier disco rígido.

La CDPedia es multiplataforma: el mismo CD, DVD o archivo comprimido se puede usar en Linux, Windows, o Mac, sin necesitar nada instalado previamente por fuera de lo que cada sistema trae normalmente.

CDPedia


¿Cómo se usa? ¿Cómo se ve?

Para usarla, lo primero es descargarla. Pueden acceder a la página del proyecto y ahí encontrarán info acerca de las cuatro versiones que tenemos actualmente, con el detalle de cuantas páginas y cuantas imágenes tiene cada una. Para bajarlo, necesitan un cliente de Torrent; para Linux a mí me gusta mucho el Deluge, que también puede usarse en Windows y Mac; otro cliente recomendado para las tres plataformas es qBittorrent.

Si descargan la versión CD o DVD, lo primero que tienen que hacer es grabarlo a un disco virgen, para lo cual necesitan una grabadora y un software para grabar. Si usan Windows y no tienen ninguno instalado, les recomiendo InfraRecorder que es software libre y muy fácil de usar. Pongan el disco generado en el equipo y ejecuten la CDPedia.

Si descargan las versión tarball, directamente descompriman los archivos en el disco rígido. Entren a la carpeta descomprimida y ejecuten la CDPedia.

¿Cómo se ejecuta la CDPedia? Bueno, depende de cada sistema. En Windows con hacer doble click en cdpedia.exe, alcanza. En Linux o Mac, si tienen bien configurado el navegador de archivos, debería funcionar haciendo doble click en cdpedia.py, pero siempre pueden recurrir a abrir una terminal, ir hasta el directorio en cuestión, y hacer ./cdpedia.py.

En cualquier caso al ejecutar ese archivo se va a levantar el Server de CDPedia, y al mismo tiempo se abrirá un navegador apuntando a ese Server local. Luego, es sólo usarla, ya que se explora y utiliza de la misma manera que la Wikipedia Online (con la excepción obvia que la CDPedia es de lectura solamente: no permite editar el contenido como sí lo hace la Wikipedia).

(a este y otros screenshots, hagan click para verlos más grandes)

Cómo se ve la CDPedia

Una decisión estratégica de la CDPedia es tomar el HTML generado por los servers de Wikipedia y usarlos casi directamente (les recortamos unos headers, optimizamos algunas cositas). Exploramos en algún momento tomar la info de la base de datos directamente, pero no logramos generar una página web igual a la de Wikipedia online.

Y eso es una fortaleza de la CDPedia: por la manera en que armamos las páginas, la forma de ver y usar las páginas, de explorar y acceder a la información, es igual a la Wikipedia online, de manera que el usuario no tiene un costo cognitivo en pasar de la versión online a offline. Es más, también se puede considerar a la CDPedia como el paso previo de consumo de contenido a la Wikipedia: una persona se puede acostumbrar a explorar las páginas, leer, cruzar y criticar la información, etc, y recién cuando tiene todo armado va a la Wikipedia Online y al resto de Internet para completar su investigación.

Más allá de la página a nivel contenido, lo que sí modificamos mucho es la barra de la izquierda. No tiene la original de Wikipedia, porque no tiene sentido al ser todo offline, así que reemplazamos los botones y enlaces por otros: hay un botón para ver una página al azar, un campo de texto de búsqueda, el logo de CDPedia, el logo de PyAr, enlace a una página de ayuda, etc...

Algo que también modificamos bastante es como señalizamos los enlaces en la página misma, en el contenido de Wikipedia. Hay principalmente tres tipos, distinguibles en cómo decoramos el texto convertido en enlace:

  • Azul: un link normal, apunta a otra página de Wikipedia que se incluyó dentro de CDPedia.
  • Rojo, subrayado con guiones: un enlace a otra página de Wikipedia pero que no fue incluida en CDPedia por razones de espacio.
  • Azul, subrayado con guiones: un link que los sacaría de CDPedia, ya que apunta a recursos online (útiles solamente si tenés Internet, claramente).

Muestra de enlaces

Otra sección que modificamos es el pie de cada página: ponemos un enlace a la misma página pero online, en Wikipedia misma, por si el usuario necesita la información actualizada. También aquí incluimos el contenido original, ponemos algún disclaimer extra, mencionamos que CDPedia es un proyecto de Python Argentina (y apuntamos al tutorial de Python que está incluido en la CDPedia).

Cabe mencionar que la CDPedia funciona también en Modo Servidor. De esta manera, se puede instalar la CDPedia en el servidor de una escuela, y que todas las computadoras del establecimiento puedan usar la información desde allí. Así logramos el efecto deseado de que los chicos puedan tener acceso al contenido de Wikipedia sin realmente tener Internet, pero sin la complicación o el incordio de tener que instalar CDPedia en cada una de las computadoras. Acá hay más instrucciones para configurarla de este modo.


¿Qué contenido tiene?

El contenido de la CDPedia está fuertemente determinado por dos características intrínsecas del proyecto: la CDPedia es estática y fácilmente distribuible en un disco o pendrive.

Digo que la CDPedia es estática porque una vez armada, no se actualiza. Es por eso una especie de "fotografía de un momento de Wikipedia" que, por definición, siempre va a estar desactualizada.

Cuando se comienza a generar una nueva versión de la CDPedia, se baja la versión más actualizada de todo el contenido de Wikipedia y se empieza a procesar. Este procesamiento puede llevar varias semanas, incluso unos meses. Entonces, cuando se libera una nueva versión de CDPedia, no incluye todos los cambios que se generaron en Wikipedia misma desde que se empezó a procesar.

Es por esto que se trata de liberar una versión de CDPedia al menos una vez por año, para que contenga la información lo más actualizada posible.

Ejemplo de un artículo

También digo que la CDPedia se puede distribuir fácilmente: sólo hace falta quemar un CD o DVD, o incluso pasarse los archivos mediante un pendrive. En casi todas las versiones (menos la más grande), por una cuestión de formato, no entra todo el contenido de la Wikipedia. Por ejemplo, para la versión 0.8.3, tenemos lo siguiente:

  • CD (693 MB): 54 mil páginas y 5% de las imágenes
  • Tarball medio (3.6 GB): 400 mil páginas y 20% de las imágenes
  • DVD (4.3 GB): Todas las páginas y 8% de las imágenes
  • Tarball grande (8.7 GB): Todas las páginas y todas las imágenes

Entonces, a menos que estemos armando el tarball grande, es evidente que tenemos que decidir cuáles páginas e imágenes van a entrar, y cuáles van a quedar afuera.

Esa decisión se toma ordenando todas las páginas por un determinado puntaje (que explico abajo), y se eligen las primeras N páginas (para el ejemplo anterior, las primeras 54 mil para el CD, las primeras 400 mil para el tarball medio, etc). Esas páginas tienen a su vez imágenes, que naturalmente también quedan ordenadas por el puntaje de las páginas: se toma un primer porcentaje de imágenes que se incluyen al 100%, otro porcentaje de imágenes que se escalan al 75%, otro porcentaje de imágenes que se escalan al 50%, y el resto no se incluye.

Analizando las páginas

Como vieron, un tema clave en la selección es darle un puntaje a las páginas. Este puntaje está formado (hoy por hoy) en base a dos factores: levemente por el largo de la página (una página larga tiene más puntaje que una corta), y fuertemente por lo que llamamos "peishranc", que es la cantidad de otras páginas que enlazan a la que estamos evaluando. Entonces, si a una página se la menciona en otras mil páginas es mucho más importante que una página que casi no se la menciona en el resto de la Wikipedia.

Otro gran detalle en lo que es "contenido" es qué hacemos para mitigar el problema de la vandalización. O sea, cómo evitamos en lo posible incluir páginas que fueron vandalizadas. Cuando comienza el proceso de generar una nueva versión de la CDPedia, como les comentaba antes, bajamos todas las páginas de Wikipedia, ¡pero no siempre bajamos la última versión! Lo que hacemos es revisar cuándo fue modificada y por quién: si fue modificada por un usuario normal, perfecto; pero si fue modificada por un usuario anónimo (como sucede en la mayoría de las vandalizaciones) nos fijamos cuando fue modificada: si fue hace más de varios días, la incluimos (asumimos que la gente de Wikipedia ya tuvo tiempo de verificar el cambio), pero si es muy reciente evitamos la última versión de la página, y agarramos la versión anterior (y aplicamos nuevamente todos estos mismos controles).


¿Cómo surgió el proyecto?

Cuenta la leyenda que el proyecto arrancó en el sprint posterior al primer PyDay de Santa Fé, en Junio del 2006, con la idea base de poder distribuir la Wikipedia a aquellos lugares que no tenían o tienen acceso a Internet (en particular teníamos en mente a escuelas de frontera o de ciudades chicas, bibliotecas de barrio, centros culturales de pueblos pequeños, etc.).

El proyecto continuó, y aunque no siempre le pudimos dedicar tiempo, tampoco nos alejamos nunca demasiado. Las mejoras en el proyecto fueron muy por ráfagas. Quiero destacar que fuimos muchos los que colaboramos con el proyecto, a lo largo de los años, ¡casi 30 personas!

Se trabajó mucho en este proyecto durante los PyCamps (los dos en Los Cocos, el de Verónica, y el de La Falda), donde muchas personas le dedicaron un buen tiempo, y también se realizó bastante durante otras reuniones, especialmente durante el 2010 y 2011.

Trabajando en un PyCamp

A modo de ejemplo, dos sprints: uno fue en un incipiente hacklab, donde se experimentó mucho sobre el índice para las búsquedas, y también durante la fundación de Wikimedia Argentina, donde se presentó por primera vez el proyecto y se realizó un gran avance en la primera parte del procesamiento de datos.

En años más cercanos yo traté de involucrar colaboradores en algunos sprints efímeros que armé, con poca suerte. Lamentablemente en el último tiempo fui principalmente sólo yo el que empujó el proyecto (lo cual es una autocrítica, más que un autoreconocimiento).

Una gran característica de la CDPedia, indiscutiblemente el proyecto más grande y más largo de Python Argentina, es que siempre se mantuvo orientado a los mismos objetivos: tener una Wikipedia offline con fines sociales (distribuir en escuelas sin conexión a Internet, que el conocimiento sea libre, etcétera), que sea divertido de hacer (es decir, hacerlo en Python), y mantenerlo libre (no sólo el producto final, que recomendamos copiarlo y repartirlo, sino el código en sí).


¿Se logró cumplir el objetivo social?

Como decía arriba, uno de los objetivos de la CDPedia es difundir el conocimiento, lograr que gente que no tenga acceso a Internet igual pueda acceder a la información de la Wikipedia, que es tan valiosa. Siendo PyAr una comunidad relativamente pequeña, era difícil escalar a tener un impacto nacional en el común de la gente.

En su momento queríamos que se viralice persona a persona: que alguien la baje y haga un par de CDs y los reparta, que los que reciben cada CD hagan a su vez varias copias y las repartan a otras personas, a escuelas, bibliotecas de barrio, etc. Pero no tuvimos mucho éxito con esa movida.

Pero resulta que Martín Varsavsky se casó, y Jimmy Wales le regaló para el casamiento la posibilidad de que se distribuya una Wikipedia offline en Argentina. Preguntó cuáles habían, la CDPedia era la que mejor se ajustaba a lo que se necesitaba, y vino Jimmy a Buenos Aires, le mostramos la CDPedia, y luego hubo una reunión en Educ.ar para terminar de acordar esto (fueron Jimmy por Wikimedia, Enrique Chaparro por Wikimedia Argentina y Alecu por PyAr).

En gran parte porque Educ.ar quería meter la CDPedia en un disco de ellos (con carátula de ellos, algunas otras páginas, etc), se logró que dicha institución becara a dos chicos de PyAr, Diego Mascialino y Hernán Olivera, para trabajar part time en esto.

Así que agarraron la versión 0.6 que recién había salido (Alecu y yo nos habíamos apurado a cerrar muchos detalles para tener algo funcionando presentable a Jimmy Wales), y entraron a darle. Esto le dio bastante impulso al desarrollo del proyecto, sumado a que también aporté regularmente al proyecto, y a que luego de que se terminara la beca Diego siguió trabajando en CDPedia, y que se sumó como "laburante regular" Santiago Piccinini.

Con todo este trabajo, y un nuevo empujón en el PyCamp del 2011, pudimos terminar de cerrar la versión 0.7, que se entregó a Educ.ar y se distribuyó a todas las escuelas del pais.

Sin embargo el mayor hito a nivel de distribución masiva de la CDPedia es que en algún momento fue incluida en las notebooks que el Estado argentino distribuye a los chicos de escuelas de todo el país como parte del programa Conectar Igualdad. Y también se la muestran a alumnos y docentes en los talleres que hacen como parte del programa.


¿Se puede espiar abajo del capot?

¿Cómo se arma la CDPedia? ¿Cómo se logra cumplir todo lo que expliqué arriba?

Es bastante sencillo: hay que bajar el código con git desde la página del proyecto en github, y luego correr un script que hace todo solo: el cdpetron.

Este script tiene bastantes opciones (especialmente para no repetir partes del proceso: que no vuelva a listar todas las páginas, que no vuelva a bajarlas, que no limpie todo antes de comenzar, etc), pero lo básico es que se le especifica de dónde tomar el código, donde bajar y dejar páginas e imágenes, y en qué idioma trabajar.

Incluso hay una manera de correrlo en modo test, para que haga solo una parte del trabajo y poder arrancar pronto a probar cosas, ideal para mezclarlo con la opción de generar una sola de las versiones:

    $ utilities/cdpetron.py --test-mode --image-type=beta . /tmp/dumpcdpedia es

El comando anterior tarda relativamente poco (menos de cinco minutos en una máquina normal y con buena conexión a Internet) y nos deja todo el proceso realizado, pero con pocas páginas.

Ver lo que obtuvimos es sencillo, porque más allá de generarnos el tarball o el .iso correspondiente, podemos probar la CDPedia directamente del directorio donde realizamos el proceso, haciendo...

    ./cdpedia.py

...lo cual levantará el server y nos abrirá el browser, tal cual si lo hiciéramos de la versión final (pero con la ventaja que podemos pararlo, cambiar el código para probar el algo, levantarlo de nuevo, ver los resultados, etc.)

¿Y cómo es el proceso que realiza? Bueno, la estructura interna (y el proceso para obtenerla) de la CDPedia está muy influida por la necesidad de optimizar al máximo la compresión y el acceso a la información, de manera de poder meter en cada formato (CD, etc...) la mayor cantidad posible de artículos e imágenes.

Podemos delinear el proceso que se realiza en en el siguiente gráfico:

Proceso de la CDPedia

El primer paso es bajar de la Wikipedia misma todas las páginas (lo que realmente tiene dos sub-pasos, un listado general de todas las páginas que nos interesan, y luego efectivamente bajarlas). Esas páginas son pasadas por diferentes preprocesadores que hacen distintos trabajos. Algunas las filtran y eliminan páginas que no queremos, otras les asignan puntajes, otras las modifican mejorándolas para nuestro objetivo, otras extraen información que va a ser útil luego.

Al final de ese preprocesamiento tenemos dos grandes resultados intermedios: los HTMLs "útiles", más un montón de metadata. Aquí se abren tres grandes ramas de trabajo.

La primera es el manejo de las imágenes. Se buscan los enlaces en las páginas, se descargan todas las imágenes necesarias (que pueden no ser todas, dependiendo de la versión generada), se reducen las que corresponden (algunas se incluyen al 75% o 50% de su tamaño) y finalmente se arman los llamados "bloques de imágenes".

Por otro lado, con los resultados intermedios se generan los "bloques de artículos".

Y finalmente, se procesan todos los títulos de las páginas más algo de metadata y se hace pasar por un complejo algoritmo matemático que nos pre-arma la información para generar los "bloques del índice".

A esta altura tengo que explicar qué son estos "bloques" de imágenes, artículos o índice. Es una estructura no demasiado compleja pero muy bien pensada para el objetivo de la CDPedia que es funcionar sin usar demasiada memoria y poco espacio en disco. Básicamente tenemos bloques de información comprimidos de forma independiente: es un equilibrio entre comprimir todo por separado, o comprimir todo junto; logramos mejor ratio de compresión que comprimiendo la info por separada, y no tenemos que descomprimir algo demasiado grande al no estar todo junto. Para decidir qué bloque consultar hay un hasheo y selección, y luego dentro de cada bloque hay un índice binario de contenidos, pero no mucho más.

Finalmente, con estos bloques, más algunos recursos estáticos (imágenes, CSSs, algo de JSs, el tutorial de Python comprimido, etc.), más el código de Python propiamente dicho para servir la CDPedia, se arman los tarballs o .ISOs.


¿En qué situación está el proyecto actualmente?

El proyecto avanza, pero lento.

Hay varios bugs abiertos, incluso algunos que son críticos porque se muestran un par de cosas feas luego de un cambio de formato de las páginas de Wikipedia, pero yo personalmente no estoy haciendo foco ahí, sino que estoy empujando un par de cambios más grandes.

Uno de ellos es lograr la internacionalización de la CDPedia. Cuando esté terminado, se van a poder crear CDPedias no sólo a partir de la Wikipedia en español, sino también de la Wikipedia en otros idiomas: portugués, aymara, guaraní, alemán, ruso, etc...

El otro cambio es más bien la construcción de una infrastructura en particular. Mi idea es tener una generación continuas de CDPedias, que se arme la CDPedia en español, y automáticamente luego se arme la de otro idioma, y otro, y otro, y otro, y luego de varios meses, vuelva a arrancar con la de español.

Trabajando

Pero, como decía, hay mil cosas para hacer.

Unos chicos en un PyCamp hicieron una app para Android que, luego de copiar los datos a mano, correría la CDPedia en cualquier teléfono o tablet (yo traté recientemente de usarlo y tuve unos problemas y no lo pude hacer andar del todo).

Otro detalle que necesita trabajo es que el código en sí está bastante feo... mezcla inglés y castellano, no cumple PEP 8 ni PEP 257, tiene poco y nada de pruebas de unidad, etc.

Si tienen ganas de participar de cualquier manera, lo principal es que se pongan en contacto con el grupo en general, a través de la lista de correo o del foro asociado (son espejo uno del otro, usen el
que sientan más cómodo). Lo mismo si desean hacer cualquier consulta, o ponerse en contacto para cualquier inquietud.

CDPedia necesita amor. Programadores con ganas de trabajar y aprender, tiempo de programador para continuar llevando este proyecto tan interesante y valioso por buen camino.

Share