Un poco de humor informático

Buenas!

No todo va a ser tecnología, os dejo una serie de gifs animados que llevan bastante tiempo pululando por Internet pero con los que me parto cada vez que los veo. Podéis encontrar muchos más en  Les joies du code (página original en francés), o en The coding love (versión en inglés).

Cuando hago una puesta en producción
Cuando hago una puesta en producción


Cuando encuentro una solución sin buscar en google
 Cuando encuentro una solución sin buscar en google


Cuando se desconecta mi ordenador antes de haber salvado todo
Cuando se desconecta mi ordenador antes de haber salvado todo


 Cuando intento corregir un bug a las 3 de la mañana
Cuando intento corregir un bug a las 3 de la mañana


Cuando mi regexp devuelve exactamente eso que esperaba
Cuando mi regexp devuelve exactamente eso que esperaba


Cuando mis colegas me proponen una pausa para el café en pleno desarrollo
Cuando mis colegas me proponen una pausa para el café en pleno desarrollo


Cuando el becario me propone realizar la web con Joomla!
Cuando el becario me propone realizar la web con Joomla!


Cuando me comunican que el módulo sobre el que he trabajado toda la semana nunca será utilizado
Cuando me comunican que el módulo sobre el que he trabajado toda la semana nunca será utilizado


Cuando ese código que no he testeado en desarrollo funciona perfecto en producción
Cuando ese código que no he testeado en desarrollo funciona perfecto en producción


Cuando los comerciales anuncian a los desarrolladores lo que han vendido al cliente
Cuando los comerciales anuncian a los desarrolladores lo que han vendido al cliente


Cuando aplico un nuevo CSS por primera vez
Cuando aplico un nuevo CSS por primera vez


Cuando el sysadmin nos da por fin el acceso a root
Cuando el sysadmin nos da por fin el acceso a root


Cuando lanzo mi script por primera vez tras varias horas de desarrollo
Cuando lanzo mi script por primera vez tras varias horas de desarrollo


Cuando me voy de fin de semana mientras que todo el mundo intenta todavía corregir bugs
Cuando me voy de fin de semana mientras que todo el mundo intenta todavía corregir bugs


Cuando me piden que eche una mano un viernes por la tarde
Cuando me piden que eche una mano un viernes por la tarde


Cuando el cliente intenta clicar sobre las maquetas
Cuando el cliente intenta clicar sobre las maquetas


Cuando un bug pasa desapercibido durante una presentación
Cuando un bug pasa desapercibido durante una presentación


Cuando el cliente quiere cambiar las especificaciones 2 días antes de la subida a producción
Cuando el cliente quiere cambiar las especificaciones 2 días antes de la subida a producción


Cuando tengo que hacer un desarrollo sin especificaciones
Cuando tengo que hacer un desarrollo sin especificaciones


Cuando mi script por fin ha funcionado
Cuando mi script por fin ha funcionado


Cuando escucho al comercial vender el proyecto al cliente
Cuando escucho al comercial vender el proyecto al cliente


Cuando el jefe de proyecto entra en la sala de trabajo

Cuando el jefe de proyecto entra en la sala de trabajo


Cuando el becario propone añadir una novedad al proyecto

Cuando el becario propone añadir una novedad al proyecto


El cliente propone hacer la página web en Flash

El cliente propone hacer la página web en Flash


Al leer las especificaciones del proyecto por primera vez

Al leer las especificaciones del proyecto por primera vez


Cuando mi compañero quiere simplificar código que funciona

Cuando mi compañero quiere simplificar código que funciona


Cuando tiro los servidores de la universidad en las prácticas

Cuando tiro los servidores de la universidad en las prácticas


Cuando mi compañero me hace entender que su código funciona finalmente

Cuando mi compañero me hace entender que su código funciona finalmente


Cuando me piden actualizar la documentación

cuando se me pide para actualizar la documentación

spacer

Ejecutando comandos desde Python

Anteriormente publiqué una introducción a Python, antes de continuar con el tutorial, dejo aquí un pequeño ejemplo de cómo se pueden realizar llamadas al shell desde Python. En concreto vamos a ver una llamada al comando ls:

#!/usr/bin/python
#-*- encoding:utf-8 -*-
#Es muy importante que la declaración de la codificación 
#de caracteres sea la primera línea antes del script.

#A.B: Comandos de sistema en Python:

#Importamos el módulo que contiene la función de llamada al sistema:
from subprocess import call

#La función call permite ejecutar el comando. Es necesario poner el
#flag de shell a True (segundo parámetro), en este caso hemos hecho
#una llamada al comando ls (con archivos ocultos) y lo hemos entubado
#en un 'more' para que pagine el resultado.
call("ls -la| more", shell=True)

Como se puede observar es bastante sencillo ejecutar comandos de shell desde Python. Para probarlo creamos un archivo nuevo "comando.py" que contenga el código anterior y lo guardamos. Luego tenemos que darle permisos de ejecución. Para no complicarnos un "chmod 777 comando.py" es suficiente. Y por último podemos ejecutarlo desde la línea de comandos con "./comando.py".


A veces los programas shell son un poco lentos en ejecución porque requieren del uso varios comandos y tuberías para realizar operaciones relativamente complejas. El comando "ls" que acabamos de ejecutar desde Python en bash podemos implementarlo directamente en Python. Probablemente los desarrollos de funcionalidades en Python sean más eficientes generalmente que los programas desarrollados en shell sobre todo en lo relacionado con manejo de ficheros, E/S, parseos de ficheros. Pues en shell script los programas se apoyan demasiado en concatenar la salida de unos comandos con otros mediante tuberías. En un ejemplo muy corto y sencillo vamos a ver cómo se ejecutaría el comando "ls" desde Python sin la ayuda del shell. Por simplicidad en el ejemplo evitamos la tubería con more:

#!/usr/bin/python
#-*- encoding:utf-8 -*-
#Es muy importante que la declaración de la codificación 
#de caracteres sea la primera línea antes del script.

#A.B: Implementación comando ls en Python

#Importamos el módulo "os" (http://docs.python.org/library/os.html) que
#permite operar con el sistema de ficheros
import os

#Obtenemos la lista de ficheros, os.getcwd() nos devuelve el directorio 
#actual y os.listdir(directorio) nos da la lista de ficheros del 
#directorio pasado como parámetro:
ficheros = os.listdir(os.getcwd())
 
#Por último, hacemos un bucle que recorre la lista de ficheros y los 
#imprimimos por pantalla: 
for f in ficheros:
 print f 
 


Eso es todo, queda en el tintero comprobar con comandos más avanzados el tiempo que tarda bash y el tiempo que tardaría Python en ejecutar la misma funcionalidad. En próximas entradas continuaré con el Tutorial de Python.
spacer

Tutorial de Python

Python es un lenguaje de moda, en la actualidad existen muchas de las ofertas de empleo que requieren conocimientos de Python, sobre todo en entidades que apuestan por el software libre y que, generalmente tienen sus aplicaciones web basadas en tecnología PHP. A rasgos generales, Python es parecido a PHP. 

Quiero aprovechar esta entrada y las próximas que escriba sobre Python para  recordar en el futuro lo que estoy aprendiendo, espero que también te sirva a tí que me lees. Y por favor, si me equivoco, corrígeme para que esto sea realmente útil.

Lo primero que debemos hacer es crear con un editor de textos o con un IDE que soporte Python un fichero que llamaremos "primer.py" que luego lanzaremos desde el intérprete de python.

Este es un ejemplo de script (módulo) en Python ("primer.py"):
#!/usr/bin/python
#-*- encoding:utf-8 -*-
#Es muy importante que la declaración de la codificación 
#de caracteres sea la primera línea antes del script.

#A.B: Probando Python

#Salida estandar
print "\nProbando la salida por estándar..."

#Creando variables de tipo primitivo
cadena = "Hola mundo"
entero = 5
real = 0.25
exponente = 1e-3
complejo = 2 + 3j

#Imprimiéndolas por pantalla
print "\n"
print "El tipo de cadena es" , type(cadena) , "y el valor es" , cadena
print "El tipo de entero es" , type(entero) , "y el valor es" , entero
print "El tipo de real es" , type(real) , "y el valor es" , real
print "El tipo de exponente es",type(exponente),"y el valor es",exponente
print "El tipo de complejo es",type(complejo),"y el valor es",complejo

#Los operadores son los típicos de todos los lenguajes. Destacar
#que se usa // para la división entera y / para la división real.
#Sin embargo, si usamos la división real con dos enteros, Python
#entiende que queremos que devuelva un entero. Es decir, que tanto
#3 // 2 como 3 / 2 devuelve 1. Para que la división sea real uno de
#los operandos debe ser real. Ej: 3 / 2.0 o bien, 3.0 / 2. 
#Otra opción es realizar un casting float(3)/2

print "\n"
print "Probando la división..."
print "3 / 2 = ", 3/2 
print "3 // 2 = ", 3//2
print "3.0 / 2 = ", 3.0 / 2 
print "float(3) / 2 = ", float(3) / 2
print "\n"

separador = "*"
#Multiplicamos el separador por 70 (Concatena 70 veces la cadena '*')
print separador * 70 

#Entrada por teclado
print "Probando la entrada por teclado. Pro favor escriba algo:"
entrada = raw_input()
print "\n"
print "Usted ha escrito: '" , entrada , "'" , "y el tipo es", type(entrada) 
print "\n"

#Vamos a definir una función
def miPrimeraFuncion(cad, val):
 """Esto saldrá en la ayuda con el comando help()"""
 print cad,val
 return "\nTerminado"

#Podemos no devolver nada, en ese caso Python devuelve None,
#que es parecido al null de Java. En Python no existen los 
#procedimientos.

#Llamamos a la función creada:
print "Llamada a la función con los parámetros cadena y complejo..."
print miPrimeraFuncion(cadena, complejo)

Para ejecutar el script debemos ir a una consola y escribir la sentencia: "python primer.py". La salida que genera este script es la siguiente:

antonio@i6253:~$ python primer.py

Probando la salida por estándar...

El tipo de cadena es <type 'str'> y el valor es Hola mundo
El tipo de entero es <type 'int'> y el valor es 5
El tipo de real es <type 'float'> y el valor es 0.25
El tipo de exponente es <type 'float'> y el valor es 0.001
El tipo de complejo es <type 'complex'> y el valor es (2+3j)

Probando la división...
3 / 2 =  1
3 // 2 =  1
3.0 / 2 =  1.5
float(3) / 2 =  1.5

**********************************************************************

Probando la entrada por teclado. Pro favor escriba algo:
Hola mundo!

Usted ha escrito: ' Hola mundo! ' y el tipo es <type 'str'>

Llamada a la función con los parámetros cadena y complejo...
Hola mundo (2+3j)

Terminado


Algunas observaciones generales e importantes son:
  • No existe símbolo para terminar la sentencia, es decir, una línea, una sentencia.
  • No hay que declarar los tipos de las variables.
  • La línea #-*- encoding: utf-8 -*- es necesaria para que python sepa cuál es la codificación de caracteres que debe tomar, en otro caso tendremos problemas con los acentos. Y debe estar en el comienzo del script.
  • El símbolo # sirve para comentarios de una sola línea.
  • Lo que escribimos entre """ y """ es un comentario de varias líneas .
  • El comentario que está debajo de la función que creamos es el que saldrá cuando pidamos la ayuda de la función. Sería algo así en el intérprete de Python: help(miPrimeraFuncion). Esto nos mostraría como ayuda lo que hemos puesto entre """ y """. 
En próximas entradas veremos un poco de orientación a objetos en Python y crearemos una clase, instanciaremos un objeto y llamaremos a sus métodos.
spacer

Multicast en Java (III) - Cliente Multicast

En la entrada anterior Multicast en Java (II) vimos un ejemplo de servidor multicast, vamos a ver ahora un cliente que sea capaz de "consumir" los datos que recibe del servidor. Recordemos el escenario: tenemos un servidor multicast que no es más que una aplicación que está enviando datos a través de una dirección de red de clase D  (multicast) por un puerto específico. 

Lo que vamos a hacer es crear un cliente que sea capaz de suscribirse a la dirección multicast en el puerto específico para recibir todo lo que emita el servidor. De forma que nuestro cliente siempre está "escuchando" al servidor multicast. Esto es útil en un entorno cliente-servidor en el que queremos que los clientes reciban los mismos datos, al mismo tiempo y de una vez, evitando enviarle datos a cada uno de los clientes.

Ejemplo de cliente

/**
* @author Antonio Bellido
*/
import java.io.*;
import java.net.*;

//Para probarlo, lanzar el MCServer y despues crear tantas 
//instancias de este como se quiera, espera a que haga el 
//join al grupo tarda unos segundos, y comienza a escribir 
//en la instancia del servidor (lo escrito saldrá en todos 
//estos clientes creados).

public class MCClient
{
public static void main (String [] args) throws IOException
{

//Creamos un socket multicast en el puerto 10000:
MulticastSocket s = new MulticastSocket (10000);

//Configuramos el grupo (IP) a la que nos conectaremos:
InetAddress group = InetAddress.getByName ("231.0.0.1");

//Nos unimos al grupo:
s.joinGroup (group);

//Leemos los paquetes enviados por el servidor multicast:
String salida = new String();
while(!salida.equals("salir"))
{

// Los paquetes enviados son de 256 bytes de maximo 
//(es adaptable)
byte [] buffer = new byte [256];

//Creamos el datagrama en el que recibiremos el paquete 
//del socket:
DatagramPacket dgp = new DatagramPacket (buffer, buffer.length);

// Recibimos el paquete del socket:
s.receive (dgp);

// Adaptamos la información al tamaño de lo que se envió 
//(por si se envió menos de 256):
byte [] buffer2 = new byte [dgp.getLength ()];

// Copiamos los datos en el nuevo array de tamaño adecuado:
System.arraycopy (dgp.getData (),
0,
buffer2,
0,
dgp.getLength ());

//Vemos los datos recibidos por pantalla:
salida = new String (buffer2);
System.out.println (salida);

}

//Salimos del grupo multicast
s.leaveGroup (group);

// Cerramos el socket:
s.close ();

}

}

spacer

Multicast en Java (II) - Servidor Multicast

En la entrada anterior Multicast en Java (I) vimos el esquema general de un servidor y un cliente multicast en JAVA. A continuación se muestra un ejemplo sencillo de servidor multicast y en la siguiente entrada mostraremos un ejemplo de cliente.

Podemos ejecutar ambos en cualquier intérprete de JAVA. El resultado será que todo lo que enviemos escribiendo por teclado desde el servidor será recibido en los clientes. El servidor seguirá enviando datos hasta que escribamos la palabra "salir". Podremos tener ejecutándose todos los clientes que queramos y todos recibirán los mismos datos que hemos escrito desde el servidor. Para probarlo podemos ejecutar una instancia del servidor desde Eclipse y todos los clientes que queramos.

Ejemplo de servidor 
**
* @author Antonio Bellido
*/
// MCServer.java
import java.io.*;
import java.net.*;
public class MCServer
{
public static void main (String[] args) throws IOException
{

System.out.println ("Arrancando el servidor multicast...\n");

//Creamos el MulticastSocket sin especificar puerto.
MulticastSocket s = new MulticastSocket ();

// Creamos el grupo multicast:
InetAddress group = InetAddress.getByName ("231.0.0.1");

// Creamos un datagrama vacío en principio:
byte [] vacio = new byte [0];
DatagramPacket dgp = new DatagramPacket(vacio, 0, group,
10000);

//Cogemos los datos a encapsular de la entrada 
//estándar (el teclado)
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
String linea = br.readLine();

//El servidor enviará los datos que lea por teclado hasta que
//se escriba "salir":
while(!linea.equals("salir"))
{

//Creamos el buffer a enviar
byte [] buffer = linea.getBytes ();

//Pasamos los datos al datagrama
dgp.setData (buffer);

//Establecemos la longitud
dgp.setLength (buffer.length);

//Y por último enviamos:
s.send (dgp);

//Leemos de la entrada estandar para evitar bucles infinitos
linea = br.readLine();

}

// Cerramos el socket.
s.close ();
}
}


Continuar leyendo en Multicast en Java (III)
spacer

Multicast en Java (I)

El Multicast es un método de direccionamiento IP. Una dirección multicast está asociada con un grupo de receptores interesados. De acuerdo al RFC 3171 las direcciones desde la 224.0.0.0 a la 239.255.255.255 están destinadas para ser direcciones de multicast. Este rango se llama formalmente "Clase D". El emisor envía un único datagrama (desde la dirección unicast del emisor) a la dirección multicast y el router se encargará de hacer copias y enviarlas a todos los receptores que hayan informado de su interés por los datos de ese emisor.

Esquema general Multicast en Java
El esquema que sigue para el servidor y el cliente es el siguiente. En entradas posteriores dejaré un ejemplo de cada uno de ellos:

El Servidor:
//Creamos el MulticastSocket sin especificar puerto.
MulticastSocket s = new MulticastSocket ();

//Creamos el grupo multicast:
InetAddress group = InetAddress.getByName ("231.0.0.1");

// Creamos un datagrama vacío en principio:
byte [] vacio = new byte [0];

//Crear el Datagrama (mensaje, tamaño msj, grupo Multicast y puerto):
DatagramPacket dgp = new DatagramPacket (vacio, 0, group, 10000);

//Enviamos el paquete
s.send (dgp);


//Cerramos el socket:
s.close ();

El Cliente:
//Creamos un socket multicast en el puerto 10000:
MulticastSocket s = new MulticastSocket (10000);

//Configuramos el grupo (IP) a la que nos conectaremos:
InetAddress group = InetAddress.getByName ("231.0.0.1");

//Nos unimos al grupo:
s.joinGroup (group);

// Recibimos el paquete del socket:
DatagramPacket dgp = new DatagramPacket (buffer, buffer.length);
s.receive (dgp);

//Salimos del grupo multicast
s.leaveGroup (group);

// Cerramos el socket:
s.close (); 

Continuar leyendo en Multicast en Java (II)
spacer