Saltar a contenido

Index

Um curso objetivo de programação em Python

Gracias al blog de Anderson Medeiros encuentro un interesante tutorial de python escrito en Portugués pero muy facilito de seguir.

Es un tutorial de introducción, rápido de leer y que me ha ayudado a recordar algunos de esos conceptos que por estar más habituado a otros lenguajes tipo Java no empleas a menudo.

Algunas cosillas que he recordado, aprendido o me han gustado.

Listas, tupas y strings

Explica bien que son listas, tuplas, diccionarios y strings. A listas y tuplas se las llama en ocasiones secuencias puesto que sus propiedades son muy parecidas. Una tupla es en realidad una lista inmutable.

Conviene tener en la cabeza lo fácil que es hacer slices (subconjuntos de secuencias) y substrings en python, incluso empleando índices negativos para empezar a contar por el final. LLega con escribir:
<br></br>>>> lista = ['a', 'b', 'c', 'd', 'e', 'f', 'g']<br></br>>>> lista[2:5]<br></br>['c', 'd', 'e']<br></br>>>> lista[2:]<br></br>['c', 'd', 'e', 'f', 'g']<br></br>>>> lista[:5]<br></br>['a', 'b', 'c', 'd', 'e']<br></br>>>> lista[:-2]<br></br>['a', 'b', 'c', 'd', 'e']<br></br>>>> lista[-2:]<br></br>['f', 'g']<br></br>

Los operadores * y + se pueden usar sobre listas, tuplas y strings. * replica n veces el elemento y + concatena.

Ejemplo para strings:
<br></br>>>> a = "exato"<br></br>>>> print a * 2<br></br>exatoexato<br></br>>>> print "quase " + a<br></br>quase exato<br></br>
Ejemplo para listas:
<br></br>>>> a = [-1, 0]<br></br>>>> b = [1, 2, 3]<br></br>>>> print b * 3<br></br>[1, 2, 3, 1, 2, 3, 1, 2, 3]<br></br>>>> print a + b<br></br>[-1, 0, 1, 2, 3]<br></br>

Para chequear si un elemento está contenido en una secuencia o diccionario se usa el operador in
<br></br>>>> "x" in "cha"<br></br>False<br></br>>>> 1 in [1,2,3]<br></br>True<br></br>

Combinar de forma implícita operaciones lógicas

Además de los operadores lógicos not, or, and python permite combinar ciertas operaciones lógicas de forma implícita:

Por ejemplo podemos comprobar un número está en un determinado rango de esta forma:
<br></br>a = 5<br></br>if 3 < a < 9:<br></br> print "Entre 3 y 9"

a = 3; b = 3; c = 2;
if a == b <= c:
print "a igual a b y b menor o igual que c"

Clausula else en bloques for y while

En los for y los while se puede emplear una claúsula else que se ejecutará cuando se salga del bloque de iteración por haber acabado la secuencia (en lugar de salir por un break)
<br></br>valores = [2, 4, 5, 2, -1]<br></br>for i in valores:<br></br> if i < 0:<br></br> print "Negativo encontrado: %d" %i<br></br> break<br></br>else:<br></br> print "Nenhum negativo encontrado"<br></br>

Valores booleanos

No está de más recordar que en python se considera falso a:

  • el booleano False
  • el valor 0 (zero)
  • una lista, diccionario, tupla o string vacios (de tamaño cero)
  • el valor especial None

Así por ejemplo para comprobar si una lista no está vacía mejor que emplear
<br></br>lista = ['a']<br></br>if (len(lista)) != 0:<br></br> print "forma poco apropiada de comprobar si una lista no está vacia"<br></br>
usaremos directamente
<br></br>if lista:<br></br> print "Lista no vacia"<br></br>

Argumentos de funciones

Existen dos formas de pasar un número variable de argumentos a una función:
<br></br>def desculpa(alvo, *motivos):<br></br> d = "Desculpas %s, mas estou doente" % alvo<br></br> for motivo in motivos:<br></br> d = d + " e %s" % motivo<br></br> return d + "."

>>> desculpa("senhor", "meu gato fugiu",
... "minha tia veio visitar")

o bien
<br></br> def equipe(diretor, produtor, **atores):<br></br> for personagem in atores.keys():<br></br> print "%s: %s" % (personagem, atores[personagem])<br></br> print "-" * 20<br></br> print "Diretor: %s" % diretor<br></br> print "Produtor: %s" % produtor

>>> equipe(diretor="Paul Anderson",
... produtor="Paul Anderson",
... Frank="Tom Cruise", Edmund="Pat Healy",
... Linda="Julianne Moore")

Frank: Tom Cruise
Edmund: Pat Healy
Linda: Julianne Moore
--------------------
Diretor: Paul Anderson
Produtor: Paul Anderson

Si tienes algún tutoirial de python que te haya gustado o algún truquillo que quieres compartir deja un comentario.

Preparar un ordenador con Windows para asistir al curso de OpenLayers.

Un par de instrucciones rápidas para el curso de OpenLayers que habrá mañana en la Escuela de Caminos en Coruña impulsado por xeoinquedos, No te asustes por el texto es mucho más fácil de lo que parece. En resumen baja los archivos que se enlazan en este post y haz doble click sobre ellos :) Los enlaces son para Windows de 32bits, si usas 64 deja un comentario y te ayudamos.

1.- Instalar Apache.

La forma más sencilla es descargar Xampp desde esta dirección [1] e instalarlo haciendo doble click. Las opciones que trae por defecto son adecuadas para la mayoría de los equipos.

Para lanzar Apache ejecuta el acceso directo que aparece en tu escritorio y luego pulsa en el botón «Start» que está a la derecha de Apache. Si salta un mensaje del antivirus pulsa en desbloquear. Para comprobar que funciona abre un navegador y escribe en la barra de direcciones http://localhost

Si se abre una página naranja ya lo tienes :)

Si tienes algún problema, tienes instrucciones más detalladas en este enlace [3]

2.- Instalar un intérprete de Python

Descarga python 2.7.1 para windows desde este enlace [2]. Instálalo mediante doble click, las opciones por defecto son una vez más adecuadas para la mayoría de los equipos.

3.- Instalar python como módulo cgi para Apache.

Descárgate este fichero [4] y cópialo dentro de la carpeta c:xamppapachemodules. Cámbiale el nombre de mod_wsgi-win32-ap22py27-3.3.so a mod_wsgi.so

A continuación abre con el WordPad el fichero c:xamppapacheconfighttpd.conf Localiza el conjunto de líneas que empiezan por el texto LoadModule y añade al final

LoadModule wsgi_module modules/mod_wsgi.so

Salva el fichero y vuelve a probar si funciona Apache.

4.- Firebug.

Lo mejor es que traigas instalado un navegador como firefox con el complemento firebug. Para instalar firebug simplemente pincha en este enlace [5] desde firefox y sigue las instrucciones.

Si usas firefox 3.6 debes descargar la versión 1.6, si usas firefox 4 debes usar la 1.7 preferiblemente. Para saber que versión de firefox tienes instalada pincha en Ayuda -> Acerca de

Aviso: En este momento la página de firebug parece caida así que si no funciona prueba con este otro enlace [8]

5.- Editor de texto

Con el bloc de notas o el WordPad es suficiente para lo que vamos a hacer pero si quieres instalar uno más potente puedes probar notepad++ [9]

6.- Copia el archivo proxy.cgi que se proporciona en los materiales del curso al directorio c:xamppcgi-bin

Y listo. Como es habitual en estas cosas, esto más difícil de escribir que de hacer.

Por último agradecer a Micho, Xurxo, Gracia, Cartolab y la Escuela de Caminos, sin los que esté curso no sería posible.

Como usar GIT tras no haber seguido el flujo de trabajo idóneo

GIT es una herramienta genial cuando eres un desarrollador disciplinado y sigues el flujo de trabajo recomendado:

<br></br>$ git checkout -b nuevaFuncionalidad<br></br>... programar<br></br>$ git add -u # añadimos automaticamente todos los ficheros indexados que han sido modificados<br></br>$ git add fichero # añadimos los no indexados<br></br>$ git commit -m "Mensaje del commit"<br></br>... más commits<br></br>$ git checkout master<br></br>$ git pull --rebase<br></br>$ git checkout nuevaFuncionalidad<br></br>$ git rebase master<br></br>... (solucionar posibles conflictos)<br></br>$ git checkout master<br></br>$ git rebase nuevaFuncionalidad<br></br>$ git push<br></br>
Pero si hay algo que me gusta, y aquí se nota que es una herramienta hecha por desarrolladores para desarrolladores, es lo bien que se comporta cuando no eres tan disciplinado o has metido la pata. Vayamos con un ejemplo (casi) real que se inicia con un viaje en tren Coruña – Vigo.

El estado del repositorio al empezar era este:

<br></br># On branch master<br></br># Your branch is ahead of 'origin/master' by 1 commit.<br></br>#<br></br># Changes to be committed:<br></br># (use "git reset HEAD ..." to unstage)<br></br>#<br></br># modified: config/text_en.properties<br></br># modified: config/text_es.properties<br></br># modified: config/text_gl.properties<br></br># new file: src/es/udc/cartolab/gvsig/tocextra/ReloadVectorialDBLayerTocMenuEntry.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br>

Se trata de la extensión para gvSIG, extTOCextra desarrollada inicialmente por Javi y liberada por Cartolab como parte del proyecto gvSIG-EIEL. Como vemos en algún momento del pasado se hizo un commit directamente sobre master que no se subió al repositorio y tenemos cuatro ficheros preparados para hacer un commit que todavía no se ha hecho.

En el viaje de vuelta Vigo – Coruña, nuestro desarrollador se pone a acabar lo que había empezado a la ida, hace un git status y se encuentra que el estado del repositorio es este:
<br></br># On branch master<br></br># Your branch is ahead of 'origin/master' by 1 commit.<br></br>#<br></br># Changes to be committed:<br></br># (use "git reset HEAD ..." to unstage)<br></br>#<br></br># modified: config/text_en.properties<br></br># modified: config/text_es.properties<br></br># modified: config/text_gl.properties<br></br># new file: src/es/udc/cartolab/gvsig/tocextra/ReloadVectorialDBLayerTocMenuEntry.java<br></br>#<br></br># Changed but not updated:<br></br># (use "git add ..." to update what will be committed)<br></br># (use "git checkout -- ..." to discard changes in working directory)<br></br>#<br></br># modified: .classpath<br></br># modified: config/text_es.properties<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br>
A base de memoria y git diff sabemos que:

  • El commit ya realizado y los archivos preparados para hacer commit constituyen una nueva funcionalidad (funcionalidad 1) que no nos interesa subir al repo por ahora
  • La modificación del .classpath y parte de lo modificado en TocExtraExtension son una pequeña refactorización que tiene sentido en si misma y que nos interesa subir como un commit separado del resto
  • El nuevo paqueta es.udc.cartolab.gvsig.tocextra.preferences, y los cambios ShowActivesTocMenuEntry, text_es.properties, y parte de los de TocExtraExtension son parte de una nueva funcionalidad (funcionalidad 2) que se empezó a programar y que todavía no está terminada. Así que nos interesa tenerla en una rama disinta de master para poder seguir trabajando sobre ella.

A la vista de esto nuestro objetivo será:

  • Tener una nueva rama con la funcionalidad 1 conservando la diferencia entre el commit ya realizado y el que tenemos preparado.
  • Una rama nueva con la refactorización en un sólo commit para luego traérnosla a master (tras haber sincronizado master con el repo) y subirla
  • Una rama nueva con la funcionalidad 2 en tantos commits como queramos para seguir trabajando.

Para conseguirlo tenemos muchos caminos alternativos, provemos uno en el que usemos distintos comandos que nos permitan ver la potencialidad de git.

Acabamos el commit que tenemos preparado

$ git commit -m "i18n for ReloadVectorialDBLayerTocMenuEntry"

Ocultamos temporalmente los cambios que nos quedan para que no nos molesten, creamos una nueva rama para la funcionalidad 1, y limpiamos el master.

<br></br>$ git status<br></br># On branch master<br></br># Your branch is ahead of 'origin/master' by 2 commits.<br></br>#<br></br># Changed but not updated:<br></br># (use "git add ..." to update what will be committed)<br></br># (use "git checkout -- ..." to discard changes in working directory)<br></br>#<br></br># modified: .classpath<br></br># modified: config/text_es.properties<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br>$ git stash<br></br># On branch master<br></br># Your branch is ahead of 'origin/master' by 2 commits.<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/

$ git checkout -b reloadDBLayers
$ git checkout master
$ git reset -hard HEAD^^ # Devolvemos la rama master al estado que tenía hace dos commits, es decir, eliminamos los cambios en local

Creamos una nueva rama para la refactorización y deshacemos la ocultación

<br></br>$ git checkout -b refactor<br></br>Switched to a new branch 'refactor'<br></br>$ git stash apply<br></br>Auto-merging .classpath<br></br>CONFLICT (content): Merge conflict in .classpath<br></br>Auto-merging config/text_es.properties<br></br>CONFLICT (content): Merge conflict in config/text_es.properties<br></br>$ git st<br></br># On branch refactor<br></br># Changes to be committed:<br></br># (use "git reset HEAD ..." to unstage)<br></br>#<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Unmerged paths:<br></br># (use "git reset HEAD ..." to unstage)<br></br># (use "git add/rm ..." as appropriate to mark resolution)<br></br>#<br></br># both modified: config/text_es.properties<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br>
Ups, el stash apply nos ha provocado un conflicto. ¿Por qué?. Tómate 15 sg para pensarlo y luego sigue leyendo…

En el commit que teniamos sin hacer había modificaciones sobre text_es.properties, cuando lo comiteamos dejamos algunas modificaciones sobre ese archivo que estaban basadas en los cambios comiteados. Como la rama «refactor» la creamos a partir de un master limpio, sin esas modificaciones cuando ejecutamos stash apply ese fichero se encuentra en un estado distinto al esperado y se produce un conflicto que no es capaz de resolver automáticamente. Si hubieramos creado la rama refactor a partir de la rama reloadDBLayers el conflicto no se hubiera producido, pero en esa rama hay cambios que no nos interesan por lo que no podemos hacer esto.

Tras la solución del conflicto el estado de repo es este:
<br></br># On branch refactor<br></br># Changed but not updated:<br></br># (use "git add ..." to update what will be committed)<br></br># (use "git checkout -- ..." to discard changes in working directory)<br></br>#<br></br># modified: .classpath<br></br># modified: config/text_es.properties<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br># no changes added to commit (use "git add" and/or "git commit -a")<br></br>

Separar los cambios realizados sobre TocExtraExtension.java

Como los cambios de la refactorización para el archivo TocExtraExtension.java están mezclados con los de la funcionalidad 2, usaremos la opción –patch de git add para separarlos separarlos. Esto nos permitirá escoger que cambios (hunks) de un archivo queremos preparar para comitear en lugar de añadir todo el archivo.
<br></br>$ git add -i src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>$ git status<br></br># On branch refactor<br></br># Changes to be committed:<br></br># (use "git reset HEAD ..." to unstage)<br></br>#<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Changed but not updated:<br></br># (use "git add ..." to update what will be committed)<br></br># (use "git checkout -- ..." to discard changes in working directory)<br></br>#<br></br># modified: .classpath<br></br># modified: config/text_es.properties<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br># src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br>$ git add .classpath<br></br>$ git commit -m "Small refactor"<br></br>[refactor 715b4da] Small refactor<br></br> 1 files changed, 18 insertions(+), 14 deletions(-)<br></br>
Como se puede ver, hemos hecho commit de sólo una parte de los cambios realizados en TocExtraExtension. Los cambios que quedan son todos los de la funcionalidad 2, así que los comiteamos a una nueva rama
<br></br>$ git checkout -b newFeature<br></br>M config/text_es.properties<br></br>M src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br>M src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br>Switched to a new branch 'newFeature'<br></br>$ git add -u<br></br>$ git add src/es/udc/cartolab/gvsig/tocextra/preferences/<br></br>$ git status<br></br># On branch newFeature<br></br># Changes to be committed:<br></br># (use "git reset HEAD ..." to unstage)<br></br>#<br></br># modified: config/text_es.properties<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/ShowActivesTocMenuEntry.java<br></br># modified: src/es/udc/cartolab/gvsig/tocextra/TocExtraExtension.java<br></br># new file: src/es/udc/cartolab/gvsig/tocextra/preferences/TOCExtraPreferencesPage.java<br></br>#<br></br># Untracked files:<br></br># (use "git add ..." to include in what will be committed)<br></br>#<br></br># bin/<br></br>$ git commit -m "WIP. new feature"<br></br>[newFeature eea0ced] WIP. new feature<br></br> 4 files changed, 137 insertions(+), 13 deletions(-)<br></br> create mode 100644 src/es/udc/cartolab/gvsig/tocextra/preferences/TOCExtraPreferencesPage.java<br></br>

Subimos al repositorio la refactorización

<br></br>$ git checkout master<br></br>$ git pull --rebase<br></br>$ git checkout refactor<br></br>$ git rebase master<br></br>$ git checkout master<br></br>$ git merge refactor<br></br>$ git push<br></br>$ git branch -D refactor<br></br>$ git checkout newFeature # para seguir trabajando<br></br>
Parece complicado, pero en realidad es más difícil de leer que de escribir una vez coges un poco de costumbre.

SigLibre2011: Taller Linked Data

Hace poco CartoLab me dió la oportunidad de asistir a las V Jornadas de SIG Libre de Girona. El primer día, y a pesar de los temores de Gonzalo, llegamos a la sede de los talleres sin perdernos, aunque es de recibo decir que caimos de nuevo en el error del año pasado de intentar aparcar en el campus de la Facultat de Letres, lo que roza lo imposible, por lo que al final aparcamos en la ciudad y subimos andando (en realidad son apenas 10 minutitos de caminata).

El taller al que fuí por la mañana iba sobre Linked Data. Para mi gusto el taller acabo siendo más bien una clase teórica, por lo que por ahora para mi se queda en el cajón de “una esas tecnologías que habría que probar un día”.

LinkedData viene siendo un avance de cara a la web semántica, que se podría explicar diciendo algo así como que el objetivo es las webs no tengan datos si no información. Y esta información pueda estar enlazada y ser enlazable, no sólo en un formato entendible por los humanos, si no en un formato apto para que las máquinas puedan relacionarse entre sí. Ese lenguaje común que las máquinas podrían interpretar y en que se asienta el linked data es el RDF. La página de preguntas frecuentes de la web de Linked Data lo deja más claro de como lo puedo hacer yo.

Un ejemplo de las posibilidades sería por ejemplo que el IGN publicara un nomenclator en RDF. Cada uno de estos ficheritos RDF podría incluir el nombre del lugar y sus coordenadas geográficas. El INE en lugar de permitir bajarte csv podría publicar ficheros en RDF donde las estadísticas estuvieran enlazadas a los RDF que publica el nomeclator, lo que aportaría componente geográfica a los datos del INE sin que el INE se tuviera que preocupar de esta componente, sólo tendrían que enlazar una fuente fiable. Un tercero podría tomar ambos datos y proporcionar un servicio con ellos, por ejemplo rastrear las ofertas de trabajo de infojobs mezcladas con los datos del paro del INE y mostrar en un mapa que tipos de trabajo se ofrecen en los sitios donde hay más paro.

Me quedo con una de las frases del ponente que decía más o menos así:

Lo bueno o lo malo de LinkedData es que el producir la información es muy costoso pero el consumirla es relativamente sencillo.

La verdad es que es una tecnología con muy buena pinta, por ejemplo ya existen herramientas que permiten servir la información de una base de datos relacional en formato RDF, e interrogar a la BD mediante SPARQL.

Para saber más:

  • Linked Data.
  • CKAN. The data hub. Ejemplos de gente usando Linked Data, a los que podríamos enlazar nuestra propia información.
  • http://geosparql.appspot.com/

Incrementar el límite de tamaño de subida de ficheros en WordPress

Cuando monta una WordPress Network el límite de tamaño de los ficheros que los distintos blogs/usuarios pueden subir mediante wordpress está fijado a 1500 KB y el máximo total de ficheros subidos está limitado a 10MB.

Para aumentar estos valores hay que ir a Administrador del sitio -> Ajustes y modificar los valores de Site upload space y Max upload file size. De paso podemos activar la posibilidad de que los usuarios suban fotos, vídeos y música. Por defecto está activada la opción de subir ficheros en general, pero al activar estos checkboxes esos tipos de ficheros serán tratados de forma especial.

Si al aumentar el Max upload file size seguimos teniendo limitaciones a la subida de ficheros seguramente es un límite impuesto por php.Para modificarlo habría que tocar el fichero php.ini, modificando estos valores. Por desgracia ese fichero sólo estará accesible cuando tengamos acceso a todos los parámetros del servidor y raramente en un hosting compartido. Pero siempre hay opciones …

  1. Si tu proveedor de hosting es Dreamhost lo primero que debes hacer es activar para tu dominio php 5.3.
  2. Independientemente de tu proveedor si tienes php 5.3 puedes modificar de formal local la configuración.
  3. Añadir al fichero phprc creado en el paso anterior las opciones que nos interesen.