<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nordri&#039;s Blog &#187; Python</title>
	<atom:link href="http://www.muspells.net/blog/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muspells.net/blog</link>
	<description>Estamos trabajando en ello...</description>
	<lastBuildDate>Fri, 13 Aug 2010 16:59:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Estructuras de Datos en Python</title>
		<link>http://www.muspells.net/blog/2010/06/estructuras-de-datos-en-python/</link>
		<comments>http://www.muspells.net/blog/2010/06/estructuras-de-datos-en-python/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 17:02:54 +0000</pubDate>
		<dc:creator>nordri</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[estructura de datos]]></category>
		<category><![CDATA[pickle]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=476</guid>
		<description><![CDATA[¿Recuerdas los tiempos en que definías un struct en lenguaje C, lo tenias que guardar en un fichero binario y luego recuperarlo haciendo un bucle leyendo cada struct? Pero claro, para ello debías conocer como estaba definida la estructura, el programador original debía proporcionar la especificación&#8230; Afortunadamente, los tiempos han cambiado, en Python disponemos del [...]]]></description>
			<content:encoded><![CDATA[<p>¿Recuerdas los tiempos en que definías un <em>struct</em> en lenguaje C, lo tenias que guardar en un fichero binario y luego recuperarlo haciendo un bucle leyendo cada <em>struct</em>? Pero claro, para ello debías conocer como estaba definida la estructura, el programador original debía proporcionar la especificación&#8230; </p>
<p>Afortunadamente, los tiempos han cambiado, en Python disponemos del módulo <em>Pickle</em> que se encargará de esa tediosa labor de guardar y recuperar datos de un fichero.</p>
<p><span id="more-476"></span></p>
<p>Para ello escribiremos una pequeña pieza de código consistente en un agenda de telefonos (el ejemplo es funcional, se puede bajar y comprobar, hacer pruebas o lo que queráis):</p>
<pre>#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#       agenda.py
#
# Pequeña agenda telefonica

import sys
import pickle # Importamos el modulo #
import os

# Mostrar los contactos: Abrimos el archivo que contiene
# el diccionario, lo cargamos en su estructura en memoria,
# y recorremos los valores
#
def showContact():
  fagenda = open(AgendaPath, "r")
  agenda = pickle.load(fagenda)
  fagenda.close
  for telefono, nombre in agenda.iteritems():
    print nombre + " ---> " + telefono

# Para añadir un contacto, tenemos que comprobar que es la primera
# vez que se ejecuta el programa, el fichero no existe, segun esta
# discriminacion, creamos el diccionario o abrimos el archivo para
# cargar el diccionario en memoria. El royo está en que para guardarlo
# el archivo tiene que estar vacio, y para leer el archivo no puede estar
# vacio, de aquí que se abra o cierre dos veces, igualmente, lo abres para
# leer y lo tienes que cerrar para abrirlo de nuevo y escribir.
#
def addContact():
  nombre = input('Nombre: ')
  telefono = input('Telefono: ')
  if os.path.isfile(AgendaPath):      # Si el fichero existe
    fagenda = open(AgendaPath, "r")   # Abrimos el fichero
    agenda = pickle.load(fagenda)     # Cargamos el diccionario
    fagenda.close                     # Cerramos el fichero
    fagenda = open(AgendaPath, "w")   # Abrimos de nuevo el fichero
    agenda[telefono] = nombre         # Actualizamos el diccionario
    pickle.dump(agenda, fagenda)      # Volcamos el diccionario al fichero
    fagenda.close                     # Cerramos el fichero
  else:
    agenda = {}
    agenda[telefono] = nombre
    fagenda = open(AgendaPath, "w")
    pickle.dump(agenda,fagenda)

if len(sys.argv) < 2:
  print "Uso: agenda.py add | show "
  exit(1)

AgendaPath = "/home/nordri/sandbox/agendatelefonica/agenda.dat"

if (sys.argv[1] == 'add'):
  addContact()
elif (sys.argv[1] == 'show'):
  showContact()
else:
  print "Error, opcion desconocida, " + sys.argv[1]
</pre>
<p>Aquí se muestra un diccionario por simplificar, pero Pickle tiene capacidad para guardar cualquier tipo abstracto que le pasemos. Posteriormente puede recuperarse desde el mismo programa o desde otro para intercambiar datos entre programas.</p>
<p>Para usar el ejemplo,</p>
<pre>$ python agenda.py add
Nombre: "Prueba"
Telefono: "111"
</pre>
<p>Para mostrar los datos</p>
<pre>$ python agenda.py show
Prueba ---> 111
Prueba2 ---> 222
Prueba3 ---> 333
</pre>
<p>Quitando la falta de originalidad en los datos, creo que ha quedado bastante claro como podemos usar este módulo para conservar e intercambiar datos abstractos.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2010/06/estructuras-de-datos-en-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notificaciones en Bash y Python</title>
		<link>http://www.muspells.net/blog/2010/06/notificaciones-en-bash-y-python/</link>
		<comments>http://www.muspells.net/blog/2010/06/notificaciones-en-bash-y-python/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 11:02:37 +0000</pubDate>
		<dc:creator>nordri</dc:creator>
				<category><![CDATA[Linux Script]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[notificacion]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=471</guid>
		<description><![CDATA[Aunque mis conocimientos se basan en estar muchas horas en la consola, escribiendo crípticos comandos, que sólo yo y Jon Maddog conocemos, utilizo un gestor de ventanas para navegar por la web, ver vídeos, escuchar música y cosas así. Puedo unir la potencia de la línea de comandos con el atractivo visual de un entorno [...]]]></description>
			<content:encoded><![CDATA[<p>Aunque mis conocimientos se basan en estar muchas horas en la consola, escribiendo crípticos comandos, que sólo yo y <a href="http://es.wikipedia.org/wiki/Jon_%22maddog%22_Hall">Jon Maddog</a> conocemos, utilizo un gestor de ventanas para navegar por la web, ver vídeos, escuchar música y cosas así. Puedo unir la potencia de la línea de comandos con el atractivo visual de un entorno de ventanas. Gracias al comando <em>notify-send</em> podemos enviar mensajes a la bandeja del sistema como por ejemplo:</p>
<p><span id="more-471"></span></p>
<pre>$ notify-send "el comando $0 ha finalizado"</pre>
<p>Así puedes relajarte y ver las ultimas novedades de tus feeds mientras esperas que las máquinas sincronicen o termine de compilar el nuevo Kernel de Linux.</p>
<p>Podemos añadir opciones en la lista de comandos, como la prioridad del mensaje, el icono que aparece, el tiempo que se muestra, etc</p>
<p>Para instalarlo, </p>
<pre># apt-get install libnotify-bin</pre>
<p>Y a jugar!</p>
<p>En Python también disponemos de un sistema de notificaciones a través del módulo <em>pynotify</em> que es igual sólo que, tenemos que escribir un poco más en el código y se ve así, </p>
<pre>if pynotify.init("program name"):
  n = pynotify.Notification("Programa terminado")
  n.show()
else:
  print "there was a problem initializing the pynotify module"
</pre>
<p>Se inicializa la clase y se van añadiendo los atributos que correspondan, como en el caso anterior, la prioridad, el icono y el tiempo de exposición. Tenemos la posibilidad de contar con un control de errores por si algo falla no muestre una fea traza de llamadas.</p>
<p>Para instalarlo, </p>
<pre># apt-get install python-notify</pre>
<p>Y a notificar xD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2010/06/notificaciones-en-bash-y-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notificando Nuevas Series Compartidas</title>
		<link>http://www.muspells.net/blog/2010/05/notificando-nuevas-series-compartidas/</link>
		<comments>http://www.muspells.net/blog/2010/05/notificando-nuevas-series-compartidas/#comments</comments>
		<pubDate>Thu, 27 May 2010 19:12:31 +0000</pubDate>
		<dc:creator>nordri</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[consola]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[incron]]></category>
		<category><![CDATA[monitorizar]]></category>
		<category><![CDATA[torrent]]></category>
		<category><![CDATA[usuario]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=318</guid>
		<description><![CDATA[Como todo buen friki que se precie, sigo un montón de series, tantas que mis usuarios se pierden cada día buscando las novedades en la carpeta compartida por NFS que tengo en mi red. El directorio compartido es /mnt/almacen/Media, un Seagate Barracuda de 1TB, de ahí cuelgan las series cada una en su directorio, muy [...]]]></description>
			<content:encoded><![CDATA[<p>Como todo buen friki que se precie, sigo un montón de series, tantas que mis usuarios se pierden cada día buscando las novedades en la carpeta compartida por NFS que tengo en mi red. El directorio compartido es /mnt/almacen/Media, un Seagate Barracuda de 1TB, de ahí cuelgan las series cada una en su directorio, muy bien ordenado.</p>
<p>Pues bien, apoyandome en el demonio Incron, he creado un sistema para notificar por correo electrónico a mi lusers cada novedad. El problema es que incron no implementa todavía la recursividad sobre subdirectorios, así que hay que supervisar cada uno por separado.</p>
<p>Este es el contenido:</p>
<pre>
bigBangTheory            Dollhouse           House          Mental               Numbers         RobinsonCrusoe    TheBeast
Bones                    EntreFantasmas      Hung           MentesCriminales     Olvidados       RomaCriminal      TheITCrowd
cocheFantastico          Eureka              incoming       Mercy                PadreDeFamilia  SamanthaWho       TheListener
ComoConociAVuestraMadre  EverybodyHateChris  kyle           Mienteme             pelisVistas     scrubs            TorchWood
csi                      FlashForward        LaPeceraDeEva  Monk                 Psych           siesta            Trauma
Deadwood                 Greek               Life           MP3s                 Reaper          Simpson           TrueBlood
Dexter                   Heroes              LifeOnMars     MujeresDesesperadas  Ritchies        StargateAtlantis  videosChicos
Docus                    Historicas          meLlamoEarl    MyOwnWorstEnemy      RobinHood       supernatural      Weeds
</pre>
<p>Escribir una línea de incrontab para cada uno es algo que no estaba dispuesto a hacer, así que se recurre a find y awk.</p>
<pre>
find /mnt/almacen/Media/ -maxdepth 1 | awk '{ print $1 " IN_MOVED_TO /home/nordri/bin/incron/nuevoMedio.py $@ $# " }'
</pre>
<p>Este comando, que debemos redireccionar a un fichero, nos mostrará esto:</p>
<pre>
[...]
/mnt/almacen/Media/Mienteme IN_MOVED_TO /home/nordri/bin/incron/nuevoMedio.py $@ $#
[...]
</pre>
<p>Que creara un monitor para el directorio, en caso que algún fichero sea movido dentro del directorio, ejecutará el comando nuevoMedio.py con los parametros $@ y $# que son la ruta completa y el nombre del archivo.</p>
<p>Existen, también dos detalles, uno es el directorio <i>históricas</i> donde guardo las series finalizadas, canceladas y discontinuadas. Esto es porque me gusta saber que series he seguido. El otro detalle, es supervisar la raíz de Media para avisar en caso que se añada una nueva serie. Las líneas que hay que añadir al incrontab son las siguientes.
<pre>
/mnt/almacen/Media/Historicas IN_MOVED_TO /home/nordri/bin/incron/nuevoHistorico.py $#
/mnt/almacen/Media IN_CREATE /home/nordri/bin/incron/nuevoDirMedio.py $#
</pre>
<p>Bien, pasemos a la programación, todos los scripts son en el básico Python que manejo, pero que resulta útil para estas cuestiones. El script nuevoMedio.py</p>
<pre>
import avisoPorEmail
import sys
def getCategoria(t):
  c = t.split("/")
  l = len(c)
  return c[l-1]
categoria  = getCategoria(sys.argv[1])
email = open("/tmp/email", "w")
email.write("En la categoria : " + categoria + "\n\nSe ha compartido un nuevo archivo multimedia: \n\n" + sys.argv[2] + "\n\n enjoy <img src='http://www.muspells.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ")
email.close()
asunto = "Nuevo archivo multimedia"
direcciones = [ #direcciones# ]
avisoPorEmail.mail('/tmp/email', asunto, direcciones, 'txt')
</pre>
<p>Simplemente, recibe la ruta del directorio compartido, elimina las barras y nos quedamos el nombre de la serie, que será la categoría, el segundo parámetro es el nombre del archivo, que lleva consigo el episodio, y todo lo que los uploaders le añaden para autopromocionarse. Se escribe la cadena en un archivo y se manda por correo a las direcciones que se le indican en el array. Hay que avisar a los usuarios que miren en spam por si acaso. A mi me pasa.</p>
<p>Los scripts de nuevoDirMedio.py y nuevoHistorico.py son muy similares.</p>
<pre>
import avisoPorEmail
import sys
import os
categoria  = sys.argv[1]
email = open("/tmp/email", "w")
email.write("Se está siguiendo una nueva serie : " + categoria + "\n\n enjoy <img src='http://www.muspells.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ")
email.close()
asunto = "Nueva Serie"
direcciones = [ #direcciones# ]
# Dar de alta el nuevo directorio en incron
os.system('/home/nordri/bin/incron/nuevoDirVigilado.sh ' + categoria)
avisoPorEmail.mail('/tmp/email', asunto, direcciones, 'txt')
</pre>
<p>Prácticamente igual, la peculiaridad aquí está en que si creamos un nuevo directorio, debemos dar de alta el monitor para incron. Para ello utilizo el siguiente script.</p>
<pre>
echo "/mnt/almacen/Media/$1 IN_MOVED_TO /home/nordri/bin/incron/nuevoMedio.py \$@ \$#" > /tmp/tareaIncron.txt
incrontab -l >> /tmp/tareaIncron.txt
incrontab /tmp/tareaIncron.txt
</pre>
<p>Simple, no? Se escribe la tarea en un archivo auxiliar, se anexa el contenido del incrontab actual y se recarga usando el archivo auxiliar como base.</p>
<p>El último es para cuando una serie se pasa al histórico, así, </p>
<pre>
import avisoPorEmail
import sys
def getCategoria(t):
  c = t.split("/")
  l = len(c)
  return c[l-1]
categoria  = getCategoria(sys.argv[1])
email = open("/tmp/email", "w")
email.write("La serie : " + categoria + "\n\nHa sido cancelada o discontinuada. Perdone las molestias")
email.close()
asunto = "Serie abandonada"
direcciones = [ #Direcciones# ]
avisoPorEmail.mail('/tmp/email', asunto, direcciones, 'txt')
</pre>
<p>Pues bien, cada vez que algo se mueva del incoming del Torrent a su directorio se avisará a los usuarios con un correo electrónico. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2010/05/notificando-nuevas-series-compartidas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cumpleaños</title>
		<link>http://www.muspells.net/blog/2008/07/cumpleanos/</link>
		<comments>http://www.muspells.net/blog/2008/07/cumpleanos/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 19:34:39 +0000</pubDate>
		<dc:creator>nordri</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://nordri.blogsome.com/2008/07/01/cumpleanos/</guid>
		<description><![CDATA[Hoy es mi cumplea&#241;os, me ha llamado mucha gente que se ha acordado, gracias a todos. Para celebrarlo he a&#241;adido una nueva funcionalidad al script de las peliculas que tanto ha dado que hablar. Ahora, cuando se a&#241;aden nuevas películas a la lista se ponen en negrita con un letrero parpadeante al lado en rojo [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy es mi <a target="_blank" href="http://es.wikipedia.org/wiki/Cumplea%C3%B1os">cumplea&ntilde;os</a>, me ha llamado mucha gente que se ha acordado, gracias a todos. Para celebrarlo he a&ntilde;adido una nueva funcionalidad al <a target="_blank" href="http://www.muspells.net/blog/2008/03/09/listado-de-peliculas/">script de las peliculas</a> que tanto ha dado que hablar.</p>
<p>Ahora, cuando se a&ntilde;aden nuevas películas a la lista se ponen en negrita con un letrero parpadeante al lado en rojo que reza &quot;Novedad&quot;.</p>
<p>Para lograr tal haza&ntilde;a, hablé con mi amigo Miguel Angel que me comentó que hiciera un <a target="_blank" href="http://linux.die.net/man/1/tree">tree</a> y luego un <a target="_blank" href="http://linux.die.net/man/1/diff">diff</a> al árbol de directorios para ver que había cambiado, nada más lejos, la solución que yo propongo se apoya en la t<a target="_blank" href="http://es.wikipedia.org/wiki/Teoria_de_conjuntos">eoría de conjuntos</a>, si tenemos un conjunto A con x elementos y un conjunto B con x + n elementos podemos hacer la operación <a target="_blank" href="http://es.wikipedia.org/wiki/Teoria_de_conjuntos#Diferencia">diferencia</a> para obtener los n elementos que difieren en los conjuntos. Estos n elementos son las novedades, así, mientras se a&ntilde;aden títulos al HTML se diferencian en si están contenidos en la lista de novedades o no.&nbsp;</p>
<p>Para obtener las listas me he apoyado en otro <a target="_blank" href="http://nordri.blogsome.com/2008/05/18/aprendiendo-python/">script Python</a> que hice en su día y que recorre el árbol de directorios, lo he modificado para que en lugar de hacer una copia espejo a&ntilde;ada cada elemento a una lista.&nbsp;</p>
<p>Como siempre, el código fuente <a href="http://pastie.org/225740" target="_blank">aquí</a>.&nbsp;</p>
<p>También me he comprado una <span class="mh-hyperlinked"><a href='http://mailhide.recaptcha.net/d?k=01YKdTHthsc-GjIi7grn-9Jw==&c=Tg9Hq9fjAXssdMddc2gcot4TO5s1yOgItsIM52-KcPiyfYQjLb7ailv2yr_wk7Zz2JoB7HnQJPQiXa66d_Tmtw==' onclick="window.open('http://mailhide.recaptcha.net/d?k=01YKdTHthsc-GjIi7grn-9Jw==&amp;c=Tg9Hq9fjAXssdMddc2gcot4TO5s1yOgItsIM52-KcPiyfYQjLb7ailv2yr_wk7Zz2JoB7HnQJPQiXa66d_Tmtw==', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;">bici.</a></span>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2008/07/cumpleanos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python y XML</title>
		<link>http://www.muspells.net/blog/2008/05/python-y-xml/</link>
		<comments>http://www.muspells.net/blog/2008/05/python-y-xml/#comments</comments>
		<pubDate>Wed, 21 May 2008 19:27:09 +0000</pubDate>
		<dc:creator>nordri</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://nordri.blogsome.com/2008/05/21/python-y-xml/</guid>
		<description><![CDATA[Sigo con la labor de traducir mis script de Bash a Python y en este caso he trabajado con el que se encarga de avisarme de que hay nuevas versiones en la documentación en inglés de Gentoo y que tengo que traducir. Soy traductor de la documentación de Gentoo y tengo a mi cargo los [...]]]></description>
			<content:encoded><![CDATA[<p>Sigo con la labor de traducir mis script de Bash a Python y en este caso he trabajado con el que se encarga de avisarme de que hay nuevas versiones en la documentación en inglés de <a href="http://www.gentoo.org/" target="_blank">Gentoo</a> y que tengo que traducir.</p>
<p>Soy traductor de la documentación de Gentoo y tengo a mi cargo los documentos de <a href="http://www.gentoo.org/doc/es/gcc-optimization.xml" target="_blank">Guía de compilación optimizada</a>, <a href="http://www.gentoo.org/doc/es/xfce-config.xml" target="_blank">Guía de configuración de XFCE</a>, la <a href="http://www.gentoo.org/doc/es/bluetooth-guide.xml" target="_blank">Guía Gentoo de Bluetooth</a> y la <a href="http://www.gentoo.org/doc/es/xen-guide.xml" target="_blank">Guía de virtualización con XEN</a>.</p>
<p>La documentación se sincroniza con cvs y está escrita en xml, el programa coge los cuatro documentos antes listados y los compara con la versión inglesa en busca de una nueva versión. En caso de nuevas versiones avisará con un correo electrónico. Es secuencial, sólo comprueba mis documentos. Se puede implementar en un bucle para saber el estado general de la documentación.</p>
<p>Bueno, el script <a href="http://pastie.caboo.se/201051" target="_blank">aquí.</a>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2008/05/python-y-xml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
