No es un bug, es una característica no documentada

domingo, 16 de abril de 2017

Cómo leer ficheros CSV con Java

19:53 Posted by Jose Ignacio Claver Paules No comments
Un CSV es un fichero de texto plano que consta de varios valores separados por comas (o punto y coma, según el caso), de modo que para procesar este tipo de ficheros en Java en principio debería bastar con leer el archivo línea a línea y partir las cadenas de texto por el separador correspondiente.

Por ejemplo, si tenemos la siguiente línea, sería bastante sencillo de procesarlo:
Programando, a, pasitos
Pero sin embargo, si nos encontramos alguna de las siguientes entradas:
"Programando a pasitos", "Claver, Inazio", "CSV, Java"
ya es más complicado, al formar las comas parte de la cadena de texto que queremos extraer. Y si además tenemos en cuenta que las comillas también pueden ser parte de ese valor, se complicaría, teniendo que poner dobles comillas para indicar que es parte del valor de una cadena.
"Programando a pasitos", "Claver, Inazio", """Leyendo CSV"" en Java"
Vamos a ver como procesar los dos tipos de CSV anteriores, el sencillo y el complejo.

domingo, 26 de febrero de 2017

Configurar Virtual Host Apache en Ubuntu

21:39 Posted by Jose Ignacio Claver Paules , No comments
Hace poco tiempo se estropeo mi ordenador y decidí que era el momento idóneo para dar el salto a una plataforma Linux. He tonteado mucho con ello pero nunca lo había tomado realmente en serio y, por considerarme 'primerizo' opté por la última versión LTS de Ubuntu, la 16.04.

El cambio no ha sido muy grande en rasgos generales, pero cuando te orientas a algo más especializado, como la programación web por ejemplo, si que he tenido ciertas dificultades para dejar todas las configuraciones como yo quería. Aquí voy a explicar como hacer una de ellas, los host virtuales de Apache.

Apache es el servidor web más popular actualmente y permite una flexibilidad asombrosa a la hora de realizar sus configuraciones. Como tengo varios proyectos en mente, me interesa poder emular varios dominios desde mi propio portátil directamente, trabajando como si de la raíz de la página web se tratase. Ahí es donde entran los virtual host.

Un host virtual es un mecanismo que permite tener funcionando más de un sitio web en una misma máquina. Estos sitios web podrán estar basados en diferentes direcciones IP o bien en distintos nombres de dominio. Ésta segunda manera es la forma con la que quiero trabajar.

martes, 20 de diciembre de 2016

Envío de mails en Python

10:53 Posted by Jose Ignacio Claver Paules No comments
Ésta será una entrada rápida.

Os pongo en situación. A partir de hoy en el trabajo debemos fichar diariamente a base de enviar un correo electrónico cuando empecemos cada jornada, tanto por la mañana como por la tarde. Los mails deberán llevar como cabecera nuestro nombre de usuario, la fecha actual en formato DDMMAA y la letra M o T dependiendo si es por la mañana o por la tarde, y en el cuerpo del mensaje deberá llevar un texto en concreto.

Bien, el caso es que soy un poco perro y, como pretendo quedarme bastante tiempo en esta empresa, no me apetece mucho tener que estar escribiendo todos los días, dos veces al día, el mismo correo. Es una tarea repetitiva que se puede automatizar fácilmente.

Y aprovechando que estoy intentando aprender Python, ¿qué lenguaje mejor para programar ese script que el de la serpiente? Leyendo un poquito vi que enviar mails con Python es tremendamente sencillo, enseguida lo veréis.

El script debía constar de dos partes, una que extrajera la fecha del sistema y la formateara como yo quisiera, y la segunda que creara un mail y lo mandase.

El código completo es el siguiente:
# -*- coding: utf-8 -*-
import smtplib
import time

'''
Calcular la hora
'''
if (time.strftime("%p") == "AM"):
 tipoHora = "M"
else:
 tipoHora = "T"

'''
Crear datos de envío
'''
remitente   = "Inazio <remitente@mail.com>"
destinatario  = "destinatario@mail.com"
asunto    = "xxxxxxxxxx" + time.strftime("%d%m%y") + tipoHora
mensaje   = "Aquí va el contenido de nuestro mensaje"

'''
Preparo el mail y agrego campos
'''
email = """From: %s 
To: %s 
MIME-Version: 1.0 
Content-type: text/html 
Subject: %s 
 
%s
""" % (remitente, destinatario, asunto, mensaje)

try:
 smtp = smtplib.SMTP('smtp.mail.com')
 smtp.login('ignacio.claver@movicoders.com', 'G62iji3@')
 smtp.sendmail(remitente, destinatario, email)
 smtp.quit()
except Exception as e:
 print(e)
Vamos a verlo paso a paso para comprender bien lo que hace.

¿Qué información necesitamos conocer?

Antes de nada, debemos tener claro qué es lo que necesitamos.
  1. Correo electrónico del remitente
  2. Correo electrónico del destinatario
  3. Dirección del servidor SMTP para envíar el mensaje
  4. Asunto y cuerpo de nuestro mensaje
Sabiendo eso, lo primero que haremos será importar las librerías necesarias, que afortunadamente se incluyen en el paquete por defecto. Son time para trabajar con tiempos, y smtplib para envío de correos electrónicos. Además agregaremos nuestra consabida cabecera de utf-8
# -*- coding: utf-8 -*-
import smtplib
import time
Ahora viene la parte en la que trabajaremos con la fecha y hora.
La hora se captura con la función time.strftime() pudiendo pasarle varios parámetros para imprimirla en cadena de texto como deseemos. A saber:

Información extraída de Python Diario.
Por lo tanto, como quiero construir una cadena que sea DDMMAA y si es por la tarde o por el día, primero averiguaré si es AM o PM y luego concatenaré el resultado en un String.
if (time.strftime("%p") == "AM"):
 tipoHora = "M"
else:
 tipoHora = "T"

'''
El asunto debe ser mi nombre de usuario, más la fecha y si es mañana o tarde. Ej: xxxxxxxxxxxx201216M
'''
asunto    = "xxxxxxxxxx" + time.strftime("%d%m%y") + tipoHora
Solo nos queda crear la información que insertaremos en el mail. Lo podemos hacer de la siguiente manera, a través de la sustitución de parámetros indicados en una cadena de texto.
email = """From: %s 
To: %s 
MIME-Version: 1.0 
Content-type: text/html 
Subject: %s
 
%s
""" % (remitente, destinatario, asunto, mensaje)
Y ahora trabajaremos configurando nuestro servidor, siempre dentro de una sección try / except.
try:
 smtp = smtplib.SMTP('smtp.mail.com')
 smtp.login('ignacio.claver@movicoders.com', 'G62iji3@')
 smtp.sendmail(remitente, destinatario, email)
 smtp.quit()
except Exception as e:
 print(e)
Lo primero es establecer la dirección de nuestro servidor SMTP para posteriormente usar. Después nos loguearemos usando el correo electrónico y la contraseña, y posteriormente usamos la función sendmail pasandole los parámetros de remitente, destinatario y el email a enviar, que establecimos anteriormente.
Nota: Según la configuración del servidor SMTP a veces no es necesario establecer usuario y contraseña.

Con todo eso ya estamos listos para generar el mail. Bastará con lanzar la aplicación desde la consola de Python e ir a revisarlo a nuestro cliente de correo electrónico. Si ha habido algún error se mostrará en la consola desde la que hemos lanzado el programa.


Si a vosotros no os llega a la bandeja de entrada deberíais revisar la sección de SPAM.

martes, 13 de diciembre de 2016

Aprendiendo Python (VII). Docstrings

0:23 Posted by Jose Ignacio Claver Paules No comments
Python es un lenguaje que se considera autodocumentado por su sencillez a la hora de ser leído. Ahora bien, cuando trabajamos en un proyecto que va creciendo en dificultad, los comentarios son dios y nosotros sus fieles y acérrimos seguidores. Nunca se pasa tan mal como cuando heredas un proyecto sin una línea de comentarios, ni un punto y coma de documentación.

Lo ideal es crear una API, que describa que es, que hace, cada objeto. ¿Qué sucede? Que a la larga es difícil de mantener, da pereza, etc.
Y ahí es cuando Python entra con su maravilloso docstrings.

Esta documentación tiene una serie de reglas, a saber:
  • Cualquier clase, función o método puede tener un string Python estándar que tiene que localizarse en la primera línea después de la definición (la línea que termina con dos puntos).
  • Ésta línea deberá estar identada al mismo nivel que el código que contenga la clase, función o método.
  • Debe explicar los parámetros que no queden muy claros
  • En caso de que se retorne algún valor también deberá indicarse
Es decir, que nuestra clase que llevamos trabajando en las anteriores entradas quedaría tal que así:
class NombreDeLaClase:
    '''
    Establece una fecha basada en el día y el mes
    '''
    
    def __init__(self, dia, mes):
        '''
        Inicializa la nueva fecha
        Params:
            - dia. Entero indicando el día de la fecha
            - mes. Entero indicando el mes de la fecha
        '''
        self.nueva_fecha(dia, mes)
        
    def nueva_fecha(self, dia, mes):
        '''
        Establece una nueva fecha
        Params:
            - dia. Entero indicando el día de la fecha
            - mes. Entero indicando el mes de la fecha
        '''
        self.dia = dia
        self.mes = mes
        
    def reiniciar(self):
        '''
        Reinicia la fecha a un valor por defecto
        Params:
            - 1. Entero. Día
            - 1. Entero. Mes
        '''
        self.nueva_fecha(1, 1)
        
    def diferencia_mes(self, otra_fecha):
        '''
        Devuelve la diferencia de meses entre dos fechas
        Params:
            - self. Nuestro objeto
            - otra_fecha. Objeto NombreDeLaClase inicializado
        Returns:
            - Entero indicando la diferencia de meses
        '''
        if (self.mes > otra_fecha.mes):
            return self.mes - otra_fecha.mes
        else:
            return otra_fecha.mes - self.mes
Ahora guardaremos el archivo con un nombre de nuestra elección. En mi caso, ejemploDocstrings.py.
Nos vamos a la consola de comandos y lanzamos nuestro programa en modo interacción con el siguiente comando
python -i ejemploDocstrings.py
Nos aparecerá un prompt esperando nuestros comandos, cosas que indica que nuestra clase ya se ha cargado y, si queremos ver el docstring en formato API que nos genera Python, escribiremos
help(NombreDeLaClase)
y veremos como automaticamente nos aparece un documento con los comentarios que hemos creado


Al poder crearse tan sencillamente, incluso podemos crearnos un script que con cada actualización nos genere la documentación de nuestro proyecto, para tenerlo constantemente actualizado.

Pronto regresare con una nueva entrada

sábado, 10 de diciembre de 2016

Aprendiendo Python 3 (VI). Orientado a objetos (II). Inicialización

18:37 Posted by Jose Ignacio Claver Paules No comments
Python, a diferencia de la mayoría de lenguajes orientados a objetos, no tiene un constructor que cree e inicialice los objetos, sino que los tiene separados, por una parte el constructor que no suele usarse salvo en casos puntuales, y por otra el inicializador.
En este último es en el que vamos a centrarnos en esta entrada.


martes, 1 de noviembre de 2016

Aprendiendo Python 3 (V). Orientado a objetos

16:03 Posted by Jose Ignacio Claver Paules 2 comments
Una vez vista la sintaxis (de forma muy básica) de Python y haber realizado los primeros ejercicios, vamos a introducirnos en la forma de programar de Python orientado a objetos.
Por si os interesa el tema y no queréis esperar, estoy siguiendo este fantástico tutorial de Jesus Conde.

Conceptualmente no se diferencia apenas de otros lenguajes:
  • Crearemos clases
  • Instanciaremos objetos
  • Les añadiremos atributos y comportamientos
  • Clases organizadas en paquetes y módulos
Como ya vimos, la sintaxis de Python es… ahorrativa. No busca complicarnos con configuraciones innecesarias.
De modo que si queremos escribir una clase basta con hacer esto:
class NombreDeLaClase:
    pass
Es decir, la forma de crearla es, primero, usando la palabra reservada class, seguida del nombre de nuestra clase y dos puntos. El nombre de la clase deberá:
  • Empezar con una letra o un guión bajo
  • Solo podrá incluir letras, guiones bajos o números.
Además, si quieres conocer mejor las guías de estilos para Python, puedes buscar la referencia PEP-0008 en su página web.

En la segunda línea será donde empezará el contenido de nuestras clases, como con las funciones, bucles, etc. Ya sabemos que Python funciona por identación, no con llaves ni corchetes. Como nuestra clase no hace absolutamente nada usaremos la palabra clave pass, que indica que no se llevará a cabo ninguna acción.

¿Eso quiere decir que no podemos hacer nada con esta clase? Bueno, no es del todo cierto. Podemos crear nuestra clase e instanciarle objetos.

Si vamos al intérprete Python podremos ver este ejemplo mucho más claro.
class NombreDeLaClase:
    pass

a = NombreDeLaClase()
b = NombreDeLaClase()
Crear instancias es, como vemos, muy similar a llamar a una función, pero realmente estamos ya creando un objeto. Tal y como me dijo el profesor la primera vez que vimos POO, “Todo es un objeto”. Luego lo remato con un “incluso las mujeres, aunque no quieran serlo”, pero eso es otra historia.

Tambien vamos a poder imprimir los objetos recién creados también.
print(a)
Lo que veremos por pantalla será algo similar a lo siguiente:
__console__.NombreDeLaClase object at 0x026CAB70
Lo que nos dirá de qué clase de objetos se trata y el espacio de memoria donde están alojados.

Puedo instanciar e imprimir objetos, vale. Pero… vaya mierda de clase has creado, ¿no?
- Hombre, pues un poco de razón sí que tienes, sí. Vamos a meterle algo de chicha en ese caso…

Vamos a empezar con los atributos de las clases. Para asignar atributos en Python no es necesario declararlos en la definición de la clase, sino que podemos asignarlos directamente en las instancias, a través de la notación de punto. Es decir objeto.atributo = valor.

Un ejemplo sería añadir dos atributos que nos indiquen el día y mes a cada una de las dos instancias creadas previamente.
a = NombreDeLaClase()
b = NombreDeLaClase()

a.dia = 31
a.mes = 10
b.dia = 1
b.mes = 11
Podemos imprimir las propiedades de la instancia a con
print(a.dia, a.mes)
Y el resultado sería 31 10.

Bueno, ahora vamos a añadir los métodos, que serán los comportamientos que tendrán los atributos de nuestras clases. Los métodos SÍ que se deben definir en la declaración de la clase.
class NombreDeLaClase:
    def reiniciar(self):
La forma de crear un método es empezar con la palabra reservada def, seguido del nombre de nuestro método y entre paréntesis los parámetros que pudiese tener, finalizando la línea con los dos puntos.

Dentro del método agregamos las acciones a realizar, en este caso que los atributos día y mes se establezcan en valor 1.
class NombreDeLaClase:
    def reiniciar(self):
        self.x = 1
        self.y = 1
Cuando usamos la palabra self estamos haciendo referencia al propio objeto. Sería el equivalente al this de Java y C#, para entendernos. La única diferencia entre métodos y funciones es que los métodos de las clases deben tener, al menos, un argumento obligatorio, este self del que estamos hablando, aunque es algo más convencional que requerido, pero a la hora de llamar al método desde la instancia NO es necesario referenciarlo como parámetro.

Ahora, si creamos una instancia de nuestra clase podremos aplicar el método que acabamos de crear.
c = NombreDeLaClase()
c.reiniciar()
Y si ahora imprimimos dichos valores veremos que ha otorgado ya el valor de 1 a cada propiedad, aunque previamente la hubiésemos inicializado a otro valor. Lo sobrescribe.

Otra forma de llamar a ese método desde el objeto como si fuese una función. En ese caso deberemos pasar como parámetro el objeto al que queremos aplicarlo.
NombreDeLaClase().reiniciar(c)
Obteniendo el mismo resultado que anteriormente.


¿Qué ocurre si no incluyésemos el parámetro self a la hora de crear nuestro método? Pues que al ejecutarlo desde la instancia nos aparecería un mensaje de error.

Básicamente nos indica que cuando llamamos al método no estamos pasando ningún argumento
¡Ajá! Sigue siendo cutrecillo, pero ya va mejorando la cosa.
- Te lo dije, solo debías esperar
- Y… ¿si quiero pasarle más de un parámetro como lo haría?
- Fácil, ahora lo vemos

Simplemente lo que hacemos es separar los parámetros por comas, manteniendo siempre el parámetro self. Agregamos un nuevo método que establezcla el día y mes que se pase en dos nuevos parámetros. Y ya que estamos modificamos nuestro método reiniciar para que llame al método nuevaFecha con los valores a establecer.

Por último vamos a insertar un tercer método que nos permite calcular la diferencia entre dos meses. Así vemos que se pueden pasar objetos complejos (instancias de clases) como parámetros.
class NombreDeLaClase:
    def nueva_fecha(self, dia, mes):
        self.dia = dia
        self.mes = mes
    def reiniciar(self):
        self.nuevaFecha(1, 1)
    def diferencia_mes(self, otra_fecha):
        if (self.mes > otra_fecha.mes):
            return self.mes – otra_fecha.mes
        else:
            return otra_fecha.mes – self.mes
Para usar la clase vamos a instanciar dos objetos nuevos.
a1 = NombreDeLaClase()
a2 = NombreDeLaClase()

a1.reiniciar()
a2.nuevaFecha(5, 11)
Ahora calcularemos la diferencia entre los meses de a1 y a2 desde el objeto a1.
print(a1.diferencia_mes(a2))
Y el resultado sería 10

Acabamos de ver como iniciarnos en la programación orientada a objetos en Python. En la siguiente entrega veremos como trabajar inicializando objetos y unas cuantas cosas más.

Salud y coding!

miércoles, 12 de octubre de 2016

Galería web responsive. HTML5 + Bootstrap + PHP + Magnific Popup

23:45 Posted by Jose Ignacio Claver Paules , , No comments
Realizando una página web me surgió la necesidad de crear una sección que sirviera de galería para que el cliente pueda mostrar todos sus trabajos.
Los requisitos que buscaba es que fuera responsive y que su carga fuese rápida. No quería perder mucho tiempo desarrollando una galería con esas características desde cero y me puse a buscar hasta que llegué a este proyecto en Git Hub de Dmitry Semenov: https://github.com/dimsemenov/Magnific-Popup.