<?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>tail -f &#124; sysadmin &#187; Python</title>
	<atom:link href="http://www.tail-f.com.ar/tag/python/feed" rel="self" type="application/rss+xml" />
	<link>http://www.tail-f.com.ar</link>
	<description>Noticias y recursos para sysadmins Unix</description>
	<lastBuildDate>Mon, 28 Nov 2011 21:44:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Sencillo parser para Apache mod_status en Python</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html#comments</comments>
		<pubDate>Sun, 31 Jul 2011 01:01:46 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[mod_status]]></category>
		<category><![CDATA[parser]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=455</guid>
		<description><![CDATA[Cuánto hace que no actualizo este blog!! Hoy estuve jugando un poco con Python y me puse a hacer un pequeño script que supongo que a otros les podrá servir como base para hacer algo más interesante. Precisamente, tengo planes para hacer algo más interesante, pero como recién están en veremos, les voy pasando esta [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif"><img class="size-full wp-image-37 alignright" title="apache1" src="http://www.tail-f.com.ar/wp-content/uploads/apache1.gif" alt="" width="210" height="210" /></a></p>
<p>Cuánto hace que no actualizo este blog!! Hoy estuve jugando un poco con Python y me puse a hacer un pequeño script que supongo que a otros les podrá servir como base para hacer algo más interesante. Precisamente, tengo planes para hacer algo más interesante, pero como recién están en veremos, les voy pasando esta pequeña base a ver si alguien me gana de mano <img src='http://www.tail-f.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Como muchos sabrán, Apache (y otros web servers) tiene un módulo llamado <a href="http://httpd.apache.org/docs/2.2/mod/mod_status.html">mod_status</a> que nos permite ver en tiempo real el estado del servidor (los requests que se están procesando, el uso del CPU, el estado de las conexiones, etc.). Esta información puede ser muy útil para hacer diagnósticos cuando está habiendo algún tipo de problema, para hacer monitoreo, etc. El módulo nos muestra una página web con la información y tiene dos interfaces: una está pensada para ser vista por seres humanos y otra para ser consultada por scripts (para ver esta segunda sólo hace falta pasarle el parámetro &#8220;?auto&#8221; en la URL). El problema es que esta segunda interfaz no nos muestra a qué dominios (virtual hosts) están dirigidos los requests que se están procesando (o si hay forma de que lo muestre yo no la encontré). Entonces me puse a hacer un sencillo script en Python para parsear la página &#8220;para seres humanos&#8221;.</p>
<p>Por suerte Python nos ofrece muchas herramientas muy útiles para este tipo de cosas, así que no me tuve que esforzar demasiado. En este caso utilicé <a href="http://docs.python.org/library/urllib2.html">urllib2</a> para acceder a la página de mod_status y <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> para parsear el HTML. Por si no lo conocen, BeautifulSoup es un muy poderoso parser para XML/HTML hecho en Python. No viene con el código fuente sino que hay que instalarlo, pero hacerlo es muy fácil:</p>
<p>En Debian/Ubuntu:</p>
<pre>apt-get install python-beautifulsoup</pre>
<p>En CentOS/RedHat:</p>
<pre>yum install python-BeautifulSoup</pre>
<p>Con easy_install:</p>
<pre>easy_install BeautifulSoup</pre>
<p>El código tiene una clase Status que es la que hace la magia y una función main() que utiliza la clase para parsear una URL e imprimir algunos datos a modo de ejemplo.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">urllib2</span><br />
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> itemgetter<br />
<span class="kw1">from</span> BeautifulSoup <span class="kw1">import</span> BeautifulSoup</p>
<p><span class="kw1">class</span> Status <span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; _url = <span class="kw2">None</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span> <span class="br0">&#40;</span><span class="kw2">self</span>, url<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._url = url</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> fetch <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span><span class="kw2">self</span>._url<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> parse <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; html = <span class="kw2">self</span>.<span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; soup = BeautifulSoup<span class="br0">&#40;</span>html<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;server_info&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span>i.<span class="kw3">string</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">for</span> i <span class="kw1">in</span> soup.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&#8216;dt&#8217;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; requests = soup.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">&#8216;table&#8217;</span><span class="br0">&#41;</span>.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&#8216;tr&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; keys = <span class="br0">&#91;</span>i.<span class="kw3">string</span> <span class="kw1">for</span> i <span class="kw1">in</span> requests.<span class="me1">pop</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> tr <span class="kw1">in</span> requests:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> n, td <span class="kw1">in</span> <span class="kw2">enumerate</span><span class="br0">&#40;</span>tr<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req<span class="br0">&#91;</span>keys<span class="br0">&#91;</span>n<span class="br0">&#93;</span><span class="br0">&#93;</span> = td.<span class="kw3">string</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> status</p>
<p><span class="kw1">def</span> main <span class="br0">&#40;</span>argv<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>argv<span class="br0">&#41;</span> &lt; <span class="nu0">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Usage %s &quot;</span>%argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span></p>
<p>&nbsp; &nbsp; status = Status<span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; data = status.<span class="me1">parse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;SERVER INFORMATION&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;==================&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> v <span class="kw1">in</span> data<span class="br0">&#91;</span><span class="st0">&#8216;server_info&#8217;</span><span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> v</p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;REQUESTS BY VHOST&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;=================&quot;</span><br />
&nbsp; &nbsp; entries = <span class="br0">&#91;</span>i<span class="br0">&#91;</span><span class="st0">&#8216;VHost&#8217;</span><span class="br0">&#93;</span> <span class="kw1">for</span> i <span class="kw1">in</span> data<span class="br0">&#91;</span><span class="st0">&#8216;requests&#8217;</span><span class="br0">&#93;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; requests = <span class="kw2">sorted</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="br0">&#40;</span>entries.<span class="me1">count</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span>, i<span class="br0">&#41;</span> <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">list</span><span class="br0">&#40;</span><span class="kw2">set</span><span class="br0">&#40;</span>entries<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>, reverse=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="st0">&quot;%d: %s&quot;</span>%<span class="br0">&#40;</span>a,b<span class="br0">&#41;</span> <span class="kw1">for</span> a,b <span class="kw1">in</span> requests<span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
<p>La forma de uso es:</p>
<pre>python status.py "http://localhost/server-status"</pre>
<p>Y en este caso la salida del script es algo así:</p>
<pre>SERVER INFORMATION
==================
Server Version: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e-fips-rhel5 DAV/2
Server Built: May 26 2011 15:14:47
Current Time: Sunday, 31-Jul-2011 00:53:59 ART
Restart Time: Saturday, 30-Jul-2011 12:07:12 ART
Parent Server Generation: 0
Server uptime:  12 hours 46 minutes 47 seconds
Total accesses: 407813 - Total Traffic: 3.7 GB
CPU Usage: u2.05 s3.23 cu52 cs0 - .125% CPU load
8.86 requests/sec - 85.0 kB/second - 9.6 kB/request
10 requests currently being processed, 8 idle workers
REQUESTS BY VHOST
=================
9: www.tail-f.com.ar
5: www.otro-dominio.com.ar
4: www.not-a-domain.com.ar
3: www.algunlado.com.ar
2: subdominio.dominio.com.ar
1: www.pepe.com.ar
1: www.no-votes-a-macri.com.ar
1: www.asd.com.ar
1: localhost</pre>
<p>Obviamente esto no es una aplicación funcional, sino un ejemplo que espero que les sirva para hacer algo más copado. Yo seguiré jugando y si hago algo un poco más interesante, ya se los mostraré.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/sencillo-parser-para-apache-mod_status-en-python.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ya salió PET: English Translation!</title>
		<link>http://www.tail-f.com.ar/programacion/python/ya-salio-pet-english-translation.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/ya-salio-pet-english-translation.html#comments</comments>
		<pubDate>Fri, 10 Sep 2010 12:12:39 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[PET]]></category>
		<category><![CDATA[traducciones]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=431</guid>
		<description><![CDATA[Hace unos días comenté la salida del primer número de la revista PET: Python Entre Todos. Como también adelanté en esa oportunidad, se descubrió que se trataba de la única revista de Python en el mundo (activa por lo menos). Así que luego de varios días de esfuerzo se tradujo el primer número y salió [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días comenté la salida del primer número de la revista <a href="http://www.tail-f.com.ar/programacion/python/pet-python-entre-todos-primera-revista-de-python.html">PET: Python Entre Todos</a>. Como también adelanté en esa oportunidad, se descubrió que se trataba de la única revista de Python en el mundo (activa por lo menos). Así que luego de varios días de esfuerzo se tradujo el primer número y salió <a href="http://revista.python.org.ar/1/html-en/">PET: English Translation</a>.</p>
<div>
<div id="attachment_432" class="wp-caption alignnone" style="width: 310px"><a href="http://www.tail-f.com.ar/wp-content/uploads/tapa-nro11.jpg"><img class="size-medium wp-image-432" title="tapa-nro1" src="http://www.tail-f.com.ar/wp-content/uploads/tapa-nro11-300x212.jpg" alt="PET: English Translation" width="300" height="212" /></a><p class="wp-caption-text">PET: English Translation</p></div>
</div>
<p>Los artículos de este número son:</p>
<ul>
<li><a href="http://revista.python.org.ar/1/html-en/pet_first_shot.html">PET First Shot</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/help.html">How you can help PET</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/pyar.html">PyAr, The History</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/hacking_python_s1.html">from gc import commonsense &#8211; Finish Him!</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/processing.html">Painless Concurrency: The multiprocessing Module</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/unittest.html">Introduction to Unit Testing with Python</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/taint.html">Taint Mode in Python</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/dinamismo.html">Applied Dynamism</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/decorators.html">Decorating code (Part 1)</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/web2py.html">Web2Py for Everybody</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/howto.html">How is this magazine made?</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/desafio.html">PET Challenge</a></li>
<li><a href="http://revista.python.org.ar/1/html-en/xkcd.html">A Bit of xkcd</a></li>
</ul>
<p>Como también ya les había adelantado, en este número tuve oportunidad de participar traduciendo dos artículos. <a href="http://revista.python.org.ar/1/html-en/pyar.html">PyAr, The History</a> de <a href="http://www.taniquetil.com.ar/plog/">Facundo Batista</a> y <a href="http://revista.python.org.ar/1/html-en/howto.html">How is this magazine made?</a> de <a href="http://lateral.netmanagers.com.ar/">Roberto Alsina</a>.</p>
<p>Además, aprovechando la ampliación del público de la revista, se ha agregado la posibilidad de hacer <a href="http://python.org.ar/pyar/Donations">donaciones</a> para la comunidad PyAr, de manera de solventar futuras actividades como impresiones del <a href="http://tutorial.python.org.ar/">tutorial de Python</a>, compra de materiales, charlas, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/ya-salio-pet-english-translation.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notificaciones de mails Prioritarios de Gmail en nuestro escritorio</title>
		<link>http://www.tail-f.com.ar/programacion/python/notificaciones-de-mails-prioritarios-de-gmail-en-nuestro-escritorio.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/notificaciones-de-mails-prioritarios-de-gmail-en-nuestro-escritorio.html#comments</comments>
		<pubDate>Sat, 04 Sep 2010 18:21:46 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Gmail]]></category>
		<category><![CDATA[IMAP]]></category>
		<category><![CDATA[imaplib]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=423</guid>
		<description><![CDATA[En estos días GMail empezó a implementar la Priority Inbox, o Prioritarios en su versión en castellano. No es nada demasiado novedoso, en realidad es una etiqueta que define a un mensaje como prioritario. Lo más interesante es que Gmail no solamente te puede mostrar por separado los mails con prioridad de los otros, sino [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_424" class="wp-caption alignright" style="width: 310px"><a href="http://www.tail-f.com.ar/wp-content/uploads/gmail-logo.jpg"><img class="size-medium wp-image-424" title="gmail-logo" src="http://www.tail-f.com.ar/wp-content/uploads/gmail-logo-300x224.jpg" alt="GMail" width="300" height="224" /></a><p class="wp-caption-text">GMail</p></div>
<p>En estos días <a href="http://www.gmail.com">GMail</a> empezó a implementar la <a href="http://mail.google.com/support/bin/answer.py?hl=en&amp;answer=186531">Priority Inbox</a>, o <a href="http://mail.google.com/support/bin/answer.py?hl=es&amp;answer=186531">Prioritarios</a> en su versión en castellano. No es nada demasiado novedoso, en realidad es una etiqueta que define a un mensaje como prioritario. Lo más interesante es que Gmail no solamente te puede mostrar por separado los mails con prioridad de los otros, sino que nos promete ir &#8220;aprendiendo&#8221; a determinar cuáles son prioritarios y cuáles no.</p>
<p>En estos días estuve probando el feature y me viene bien. Yo recibo muchos mails por día, la mayoría de distintas listas de correo. Y como soy muy obsesivo, cada vez que tengo un mensaje nuevo voy a ver de qué se trata y &#8220;marcarlo como leído&#8221;. Este feature me permite perocuparme solamente por los prioritarios y dejar los menos importantes (como los de las listas) para más tarde.</p>
<p>Hoy pensé: &#8220;qué bueno estaría tener una aplicación que me notifique solamente de los mails importantes&#8221;. Ya existen varios <a href="http://www.google.com/search?&amp;q=gmail+notifier&amp;ie=utf-8&amp;oe=utf-8">notifiers para Gmail</a>, tanto de Google o de terceros, para Firefox o para el Desktop. Pero supongo que todavía no habrán implementado esta posibilidad de solamente avisarte de los mensajes prioritarios. Así que lo que hice fue hacerlo en Python que es muuuy fácil.</p>
<p>En su versión simplificada, ver si hay mails &#8220;Importantes&#8221; y notificarlo es tan sencillo como esto:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">imaplib</span><br />
<span class="kw1">import</span> pynotify<br />
<span class="kw1">from</span> <span class="kw3">email</span>.<span class="me1">header</span> <span class="kw1">import</span> decode_header<br />
<span class="kw1">from</span> <span class="kw3">email</span>.<span class="kw3">parser</span> <span class="kw1">import</span> Parser</p>
<p>host = <span class="st0">&#8216;imap.gmail.com&#8217;</span><br />
port = <span class="nu0">993</span><br />
username = <span class="st0">&#8216;usuario@gmail.com&#8217;</span><br />
password = <span class="st0">&#8216;passwordsupersecreto&#8217;</span></p>
<p><span class="kw1">def</span> get_header <span class="br0">&#40;</span>msg, header<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Gets a header from a message&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; header = decode_header<span class="br0">&#40;</span>msg.<span class="me1">get</span><span class="br0">&#40;</span>header<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>header<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">unicode</span><span class="br0">&#40;</span>header<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, header<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">encode</span><span class="br0">&#40;</span><span class="st0">&#8216;utf8&#8242;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> header<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span></p>
<p><span class="kw1">if</span> <span class="kw1">not</span> pynotify.<span class="me1">init</span><span class="br0">&#40;</span><span class="st0">&quot;GMail Important Messages&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Failed to initialize pynotify&quot;</span><br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></p>
<p>client = &nbsp;<span class="kw3">imaplib</span>.<span class="me1">IMAP4_SSL</span><span class="br0">&#40;</span>host, port<span class="br0">&#41;</span><br />
<span class="kw1">if</span> <span class="kw1">not</span> client.<span class="me1">login</span><span class="br0">&#40;</span>username, password<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Failed to login&quot;</span><br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></p>
<p>status, data = client.<span class="kw3">select</span><span class="br0">&#40;</span><span class="st0">&#8216;[Gmail]/Important&#8217;</span><span class="br0">&#41;</span><br />
<span class="kw1">if</span> status != <span class="st0">&#8216;OK&#8217;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Failed to select Important label&quot;</span><br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></p>
<p>status, data = client.<span class="me1">search</span><span class="br0">&#40;</span><span class="kw2">None</span>, <span class="st0">&#8216;(UNSEEN)&#8217;</span><span class="br0">&#41;</span><br />
<span class="kw1">if</span> status == <span class="st0">&#8216;OK&#8217;</span> <span class="kw1">and</span> data<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> != <span class="st0">&#8221;</span>:<br />
&nbsp; &nbsp; <span class="kw1">for</span> msg_id <span class="kw1">in</span> <span class="kw2">sorted</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> msg_id != <span class="st0">&#8221;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status, data = client.<span class="me1">fetch</span><span class="br0">&#40;</span>msg_id, <span class="st0">&#8216;(RFC822)&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> status == <span class="st0">&#8216;OK&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg = Parser<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">parsestr</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span>get_header<span class="br0">&#40;</span>msg, <span class="st0">&#8216;From&#8217;</span><span class="br0">&#41;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get_header<span class="br0">&#40;</span>msg, <span class="st0">&#8216;Subject&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Failed to fetch message #%s&quot;</span> % <span class="kw2">str</span><span class="br0">&#40;</span>msg_id<span class="br0">&#41;</span></div>
<p>Ese código lo que hace es inicializar pynotify, conectarse al servidor IMAP de GMail usando <a href="http://docs.python.org/library/imaplib.html">imaplib</a>, autenticarse con el user y password provisto, seleccionar la etiqueta &#8220;[Gmail]/Important&#8221; y ver si hay mensajes sin leer. En caso de que haya itera sobre ellos, obtiene su contenido (para sacar el remitente y el asunto) y lanza un mensaje de notificación.</p>
<p>Para convertir eso en una aplicación básicamente hace falta meterlo en un while y corregir un detalle que es que el fetch del mensaje lo marca como leído (y eso no es algo que queramos en un simple notificador), así que hay que volver a marcarlo como no leído. Eso y algunos toques cosméticos es lo que hice en <a href="http://pastebin.com/9SqPTLJS">el script completo</a>.</p>
<p>Por supuesto se trata solo de una prueba de concepto y a una aplicación completamente funcional deberían hacersele algunas correcciones más. Pero creo que es una idea divertida como para que otros puedan hacer algo mejor.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/notificaciones-de-mails-prioritarios-de-gmail-en-nuestro-escritorio.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PET: Python Entre Todos, primera revista de Python</title>
		<link>http://www.tail-f.com.ar/programacion/python/pet-python-entre-todos-primera-revista-de-python.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/pet-python-entre-todos-primera-revista-de-python.html#comments</comments>
		<pubDate>Sun, 22 Aug 2010 14:41:03 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[PET]]></category>
		<category><![CDATA[revista]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=412</guid>
		<description><![CDATA[A esta altura ya es una noticia vieja, pero quizás alguno no se haya enterado de que la semana pasada salió publicada la revista PET: Python Entre Todos. La revista es una producción colaborativa de la Comunidad PyAr, con artículos de muy alto nivel de distintos participantes de la lista y el esfuerzo especial de [...]]]></description>
			<content:encoded><![CDATA[<p>A esta altura ya es una noticia vieja, pero quizás alguno no se haya enterado de que la semana pasada salió publicada la revista <a href="http://revista.python.org.ar/">PET: Python Entre Todos</a>.</p>
<p>La revista es una producción colaborativa de la <a href="http://python.org.ar/">Comunidad PyAr</a>, con artículos de muy alto nivel de distintos participantes de la lista y el esfuerzo especial de sus dos editores, Roberto Alsina y Emiliano Dalla Verde Marcozzi.</p>
<div id="attachment_413" class="wp-caption alignright" style="width: 310px"><a href="http://www.tail-f.com.ar/wp-content/uploads/tapa-nro1.jpg"><img class="size-medium wp-image-413 " title="PET: Python Entre Todos Num. 1" src="http://www.tail-f.com.ar/wp-content/uploads/tapa-nro1-300x212.jpg" alt="PET: Python Entre Todos Num. 1" width="300" height="212" /></a><p class="wp-caption-text">PET: Python Entre Todos Num. 1</p></div>
<p>Los artículos incluidos en la revista son:</p>
<ul>
<li>PET First Shot</li>
<li>Cómo contribuir a PET</li>
<li> PyAr, la historia</li>
<li> from gc import commonsense &#8211; Finish Him!</li>
<li> Concurrencia Indolora: el módulo processing</li>
<li> Introducción a Unit Testing con Python</li>
<li> Taint Mode en Python</li>
<li> Dinamismo Aplicado</li>
<li> Decorando Código (Parte 1)</li>
<li> Web2Py Para Todos</li>
<li> ¿Cómo Está Hecha Esta Revista?</li>
<li> Desafío PET</li>
<li> Un poco de xkcd</li>
</ul>
<p>La publicación fue todo un éxito porque se dinfundió rápidamente por Internet con la ayuda de diversos medios: blogs, twitter, barrapunto, etc. En mi opinión esta buena recepción se debió dos factores clave: la calidad del contenido que es realmente muy alta y que gracias a las tecnologías de software libre utilizadas para la edición de la revista, la misma pudo ser publicada en múltiples formatos: HTML online, PDF en distintos layouts y para e-book readers en ePub y Mobi. A todos ellos se puede acceder en la página del <a href="http://revista.python.org.ar/1/html/">primer número de la revista</a>.</p>
<p>Además, al poco tiempo de publicada la revista, Roberto descubrió que <a href="http://revista.python.org.ar/">PET</a> es la primera revista de Python&#8230; en el mundo!. Esto animó a la comunidad a crear una versión en inglés para poder difundirla a un mayor público. Personalmente tuve la opotunidad de colaborar traduciendo dos artículos, &#8220;<a href="http://revista.python.org.ar/1/html/genesispyar.html">PyAr, la historia</a>&#8221; de <a href="http://www.taniquetil.com.ar/plog/">Facundo Batista</a> y &#8220;<a href="http://revista.python.org.ar/1/html/comohacer.html">¿Cómo Está Hecha Esta Revista?</a>&#8221; de <a href="http://lateral.netmanagers.com.ar/">Roberto Alsina</a>. De esta manera, si no puedo aportar con un artículo interesante, por lo menos puedo colaborar para que las cosas interesantes que escriben otros puedan llegar a un público más amplio.</p>
<p>Así que seguramente pronto estemos anunciando la versión en inglés del número 1 de PET. Y en el futuro, según entiendo, la idea es poder incorporar artículos de colaboradores internacionales en ambas versiones de la revista.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/pet-python-entre-todos-primera-revista-de-python.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Una vueltita por las Charlas Abiertas de Python en La Tribu</title>
		<link>http://www.tail-f.com.ar/programacion/python/una-vueltita-por-las-charlas-abiertas-de-python-en-la-tribu.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/una-vueltita-por-las-charlas-abiertas-de-python-en-la-tribu.html#comments</comments>
		<pubDate>Sat, 21 Aug 2010 18:21:00 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Charlas]]></category>
		<category><![CDATA[Desarrollo web]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=409</guid>
		<description><![CDATA[Hoy pude darme una vuelta, por primera vez, por las Charlas Abiertas de Python en La Tribu. Le robé un tiempo al estudio y me dirigí a Lambaré 873 junto a un amigo, a ver qué tal estaban esas charlas. No esperaba encontrar grandes revelaciones porque la charla a la que iba era la de [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_391" class="wp-caption alignright" style="width: 310px"><a href="http://www.tail-f.com.ar/wp-content/uploads/charlasabiertaspytribu.png"><img class="size-medium wp-image-391" title="charlasabiertaspytribu" src="http://www.tail-f.com.ar/wp-content/uploads/charlasabiertaspytribu-300x136.png" alt="" width="300" height="136" /></a><p class="wp-caption-text">Charlas Abiertas de Python en La Tribu</p></div>
<p>Hoy pude darme una vuelta, por primera vez, por las <a href="http://www.tail-f.com.ar/programacion/python/ciclo-de-charlas-abiertas-de-python-argentina-en-la-tribu.html">Charlas Abiertas de Python en La Tribu</a>. Le robé un tiempo al estudio y me dirigí a Lambaré 873 junto a un amigo, a ver qué tal estaban esas charlas.</p>
<p>No esperaba encontrar grandes revelaciones porque la charla a la que iba era la de Introducción al Desarrollo Web I, a cargo de Alejandro Cura, y yo ya trabajo en el rubro hace algunos años. Sin embargo me interesaba verle las caras a algunos miembros de la <a href="http://python.org.ar/">comunidad</a> por quienes tengo un gran respeto.</p>
<p>Me encontré con un ámbito muy amigable, lleno de gente deseosa de aprender. Me alegró mucho encontrar algunas personas &#8220;mayores&#8221; (por lo menos mayores al tipo de gente que uno suele conocer en este acotado segmento del mercado laboral), muy interesadas y participativas. La charla estuvo muy bien, era una introducción para quienes no tienen idea de en qué consiste hacer un sitio web (y preparatoria para la próxima charla que dará algunos conceptos básicos de <a href="http://www.web2py.com/">Web2Py</a>). Me pareció muy copado que se le diera un poco de bola al protocolo HTTP y cómo funciona, porque en mi experiencia laboral me he encontrado con desarrolladores que pueden manejar muy bien algunos lenguajes como PHP, Javascript o HTML pero no tienen idea de cómo llegan esas cosas &#8220;a la mesa&#8221; del browser.</p>
<p>Incluso me encontré aprendiendo una cosita de CSS que no sabía y era la posibilidad de incluir tipografías externas (que quisiera ver qué tan compatible es con la bosta de IE, pero que me resultó muy útil).</p>
<p>Me hubiera gustado quedarme a la charla siguiente del eminente <a href="http://lateral.netmanagers.com.ar/">Roberto Alsina</a>, pero lamentablemente tenía que volver a la cueva a estudiar.</p>
<p>Felicito desde este humilde lugar el enorme trabajo que está realizando la comunidad <a href="http://python.org.ar/">PyAr</a> organizando estas charlas que permiten acercar herramientas a la sociedad para conocer y apropiarse de las nuevas tecnologías asociadas a la informática e Internet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/una-vueltita-por-las-charlas-abiertas-de-python-en-la-tribu.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cmd: Creando una consola interactiva con Python</title>
		<link>http://www.tail-f.com.ar/programacion/python/cmd-creando-una-consola-interactiva-con-python.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/cmd-creando-una-consola-interactiva-con-python.html#comments</comments>
		<pubDate>Sat, 24 Jul 2010 20:42:50 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Cmd]]></category>
		<category><![CDATA[Consola Interactiva]]></category>
		<category><![CDATA[Directadmin]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=400</guid>
		<description><![CDATA[Siguiendo con los ejemplos de los grandes recursos que ofrece la standard library de Python, así como el otro día hablé sobre BaseHTTPServer, hoy voy a hablar de Cmd. Cmd es un módulo que nos permite crear una consola interactiva, como la propia consola de Python, en unas pocas líneas. La consola incluye manejo de [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_402" class="wp-caption alignright" style="width: 290px"><a href="http://www.tail-f.com.ar/wp-content/uploads/smilingpython.gif"><img class="size-full wp-image-402 " title="Python" src="http://www.tail-f.com.ar/wp-content/uploads/smilingpython.gif" alt="Python" width="280" height="280" /></a><p class="wp-caption-text">Python</p></div>
<p>Siguiendo con los ejemplos de los grandes recursos que ofrece la standard library de Python, así como el otro día hablé sobre <a href="http://www.tail-f.com.ar/programacion/python/python-basehttpserver-un-servidor-http-en-unas-pocas-lineas.html">BaseHTTPServer</a>, hoy voy a hablar de <a href="http://docs.python.org/library/cmd.html">Cmd</a>.</p>
<p>Cmd es un módulo que nos permite crear una consola interactiva, como la propia consola de Python, en unas pocas líneas. La consola incluye manejo de distintos prompts, hooks para la ejecución de comandos, manejo de historial, ayuda general y por comando, y autocompletado de comandos y parámetros, etc. Lo único que tenemos que hacer para implementarla es extender la clase <strong>cmd.Cmd</strong> e implementar métodos <strong>do_*</strong> para los distintos comandos que queramos definir.</p>
<p>Veamos las opciones disponibles con un ejemplo muy sencillo:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1"># -*- coding: utf-8 -*-</span><br />
<span class="kw1">import</span> <span class="kw3">cmd</span></p>
<p><span class="kw1">class</span> Console<span class="br0">&#40;</span><span class="kw3">cmd</span>.<span class="me1">Cmd</span><span class="br0">&#41;</span>:</p>
<p>&nbsp; &nbsp; prompt = <span class="st0">&quot;&gt; &quot;</span></p>
<p>&nbsp; &nbsp; _colors = <span class="br0">&#123;</span><span class="st0">&#8216;red&#8217;</span>: <span class="st0">&#8216;#FF0000&#8242;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#8216;white&#8217;</span>: <span class="st0">&#8216;#FFFFFF&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#8216;black&#8217;</span>: <span class="st0">&#8216;#000000&#8242;</span><span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span> <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Constructor&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">cmd</span>.<span class="me1">Cmd</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> do_hello <span class="br0">&#40;</span><span class="kw2">self</span>, name<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Says hello to someone&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Hello %s!&quot;</span> % name</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> do_get_color <span class="br0">&#40;</span><span class="kw2">self</span>, color<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Prints out the hex representation of a color&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> color <span class="kw1">in</span> <span class="kw2">self</span>._colors:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;%s: %s&quot;</span> % <span class="br0">&#40;</span>color, <span class="kw2">self</span>._colors<span class="br0">&#91;</span>color<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;I don&#8217;t know: %s&quot;</span> % color</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> complete_get_color <span class="br0">&#40;</span><span class="kw2">self</span>, text, line, begidx, endix<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Complete function for get_color&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#91;</span>i <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">self</span>._colors <span class="kw1">if</span> i.<span class="me1">startswith</span><span class="br0">&#40;</span>text<span class="br0">&#41;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> do_quit <span class="br0">&#40;</span><span class="kw2">self</span>, s<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Bye, bye&#8230;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">True</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> help_quit <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Quits the console&quot;</span></p>
<p>&nbsp; &nbsp; do_EOF = do_quit<br />
&nbsp; &nbsp; help_EOF = help_quit</p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; console = Console<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; console.<span class="me1">cmdloop</span><span class="br0">&#40;</span><span class="st0">&quot;Hola!&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; console.<span class="me1">do_quit</span><span class="br0">&#40;</span><span class="kw2">None</span><span class="br0">&#41;</span></div>
<p><strong>Inicialización</strong></p>
<p>Lo primero que hacemos es definir la clase Console que extiende cmd.Cmd. Luego definimos la propiedad pública &#8220;prompt&#8221;, que será el prompt de la consola (por default &#8220;(Cmd)&#8221;).</p>
<p><strong>Un método básico</strong></p>
<p>Luego tenemos el método do_hello que toma un argumento y le dice hola al argumento. Notesé que el texto que definimos en el comentario (&#8220;Says hello to someone&#8221;), además de ser la documentación de la función es tomada por Cmd para mostrarlo como ayuda del comando. Si en la consola ponemos &#8220;? hello&#8221; o &#8220;help hello&#8221;, se imprimirá esa cadena.</p>
<p><strong>Autocompletado</strong></p>
<p>A continuación tenemos el método do_get_colors que imprime el código hexadecimal de un color, según el diccionario _colors. Además de tener su texto de ayuda, a continuación tenemos el método complete_get_colors que lo que hace es manejar el autocompletado de los parámetros. Aquí lo que hacemos es ver el texto que se tipeó y devolver todas las claves del diccionario _colors que empiecen con ese texto.</p>
<p><strong>Salir de la consola</strong></p>
<p>Para salir del loop de la consola un método tiene que devolver True. Para ello definimos el método do_quit. Aquí imprimimos un saludo y salimos. Las novedades son, por un lado, la función help_quit que cumple la misma función que el docstring: imprime la ayuda del comando quit. Y además duplicamos la función do_quit como do_EOF (y help_quit como help_EOF). De esta forma, cuando la consola reciba EOF (es decir, Ctrl+D) ejecutará do_quit y saldrá.</p>
<p><strong>Ejecutando la consola</strong></p>
<p>Por último, al final del código instanciamos la clase Console y ejecutamos el método cmdloop() que inicia el loop de la consola. De paso agregamos el handling de la excepción KeyboardInterrupt (es decir, Ctrl+C) para que ejecute do_quit y cierre la consola adecuadamente.</p>
<p><strong>Otro ejemplo</strong></p>
<p>Así como hice la última vez, les dejo otro ejemplo más completo en el que anduve trabajando. En este caso es parte del código de mi modesto proyecto <a href="http://www.tail-f.com.ar/paneles-de-control/directadmin/python-directadmin-api-para-conectarse-a-directadmin-desde-python.html">python-directadmin</a>. Se trata de <a href="http://code.google.com/p/python-directadmin/wiki/DaConsole">DAConsole</a>, una pequeña consola interactiva para interactuar con Directadmin, donde implemento todas estas cosas vistas aquí, además de la posibilidad de crear consolas anidadas.</p>
<p><a href="http://code.google.com/p/python-directadmin/source/browse/trunk/scripts/da_console">Ver código de DAConsole</a>.</p>
<p><strong>Referencias</strong></p>
<ul>
<li><a href="http://docs.python.org/library/cmd.html">Módulo Cmd en la documentación de Python</a></li>
<li><a href="http://wiki.python.org/moin/CmdModule">Módulo Cmd en la wiki de Python</a> (con explicaciones y ejemplos más completos)</li>
<li><a href="http://code.google.com/p/python-directadmin/source/browse/trunk/scripts/da_console">DAConsole</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/cmd-creando-una-consola-interactiva-con-python.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Pegá el folleto de las Charlas de Python en tu lugar de trabajo!</title>
		<link>http://www.tail-f.com.ar/programacion/python/pega-el-folleto-de-las-charlas-de-python-en-tu-lugar-de-trabajo.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/pega-el-folleto-de-las-charlas-de-python-en-tu-lugar-de-trabajo.html#comments</comments>
		<pubDate>Fri, 16 Jul 2010 17:39:29 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Charlas]]></category>
		<category><![CDATA[La Tribu]]></category>
		<category><![CDATA[PyAr]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=390</guid>
		<description><![CDATA[Como les contaba hace unos días, el 24 de julio empieza el Ciclo de Charlas Abiertas de Python Argentina en la sede del Colectivo La Tribu, Lambaré 873. La entrada es libre y gratuita. Se pasará una gorra voluntaria durante los cursos para hacer frente a viáticos y gastos generales. No hace falta registrarse, pero [...]]]></description>
			<content:encoded><![CDATA[<p>Como les contaba hace unos días, el 24 de julio empieza el <a href="http://www.tail-f.com.ar/programacion/python/ciclo-de-charlas-abiertas-de-python-argentina-en-la-tribu.html">Ciclo de Charlas Abiertas de Python Argentina</a> en la sede del Colectivo La Tribu, Lambaré 873.</p>
<div id="attachment_391" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.tail-f.com.ar/wp-content/uploads/charlasabiertaspytribu.png"><img class="size-medium wp-image-391" title="charlasabiertaspytribu" src="http://www.tail-f.com.ar/wp-content/uploads/charlasabiertaspytribu-300x136.png" alt="" width="300" height="136" /></a><p class="wp-caption-text">Charlas Abiertas de Python el La Tribu</p></div>
<p>La entrada es libre y gratuita. Se pasará una gorra voluntaria durante los cursos para hacer frente a viáticos y gastos generales.<br />
No hace falta registrarse, pero vengan temprano para asegurarse un lugar porque los cupos son limitados.</p>
<p>La gente de <a href="http://python.org.ar/pyar/Inicio">PyAr</a> está invitando a pegar <a href="http://www.tail-f.com.ar/files/CharlasAbiertasPythonLaTribu2010.pdf">el folleto</a> de las charlas en facultades y lugares de trabajo.</p>
<p><strong>Mapa:</strong></p>
<div align="center">
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=Lambar%C3%A9+873,+ciudad+de+buenos+aires&amp;sll=37.0625,-95.677068&amp;sspn=47.167389,89.296875&amp;ie=UTF8&amp;hq=&amp;hnear=Lambar%C3%A9+873,+Almagro,+Ciudad+Aut%C3%B3noma+de+Buenos+Aires,+Argentina&amp;z=14&amp;ll=-34.604634,-58.430473&amp;output=embed"></iframe><br /><small><a href="http://maps.google.com/maps?f=q&amp;source=embed&amp;hl=en&amp;geocode=&amp;q=Lambar%C3%A9+873,+ciudad+de+buenos+aires&amp;sll=37.0625,-95.677068&amp;sspn=47.167389,89.296875&amp;ie=UTF8&amp;hq=&amp;hnear=Lambar%C3%A9+873,+Almagro,+Ciudad+Aut%C3%B3noma+de+Buenos+Aires,+Argentina&amp;z=14&amp;ll=-34.604634,-58.430473" style="color:#0000FF;text-align:left">View Larger Map</a></small></div>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/pega-el-folleto-de-las-charlas-de-python-en-tu-lugar-de-trabajo.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python BaseHTTPServer: un servidor HTTP en unas pocas líneas</title>
		<link>http://www.tail-f.com.ar/programacion/python/python-basehttpserver-un-servidor-http-en-unas-pocas-lineas.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/python-basehttpserver-un-servidor-http-en-unas-pocas-lineas.html#comments</comments>
		<pubDate>Thu, 15 Jul 2010 20:25:01 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Load average]]></category>
		<category><![CDATA[Servidor HTTP]]></category>
		<category><![CDATA[Status]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=384</guid>
		<description><![CDATA[Python es un lenguaje tan poderoso que me sorprende constantemente. Particularmente su librería standard incluye tantas cosas maravillosas que lleva tiempo ir descubriéndolas todas. Hoy voy a hablar de BaseHTTPServer un módulo de Python 2.x (en 3.x se llama http.server) que nos permite implementar un servidor web en muy pocas líneas de código. Es la [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_386" class="wp-caption alignright" style="width: 277px"><a href="http://www.tail-f.com.ar/wp-content/uploads/python.png"><img class="size-full wp-image-386" title="python" src="http://www.tail-f.com.ar/wp-content/uploads/python.png" alt="Python" width="267" height="235" /></a><p class="wp-caption-text">Python</p></div>
<p>Python es un lenguaje tan poderoso que me sorprende constantemente. Particularmente su librería standard incluye tantas cosas maravillosas que lleva tiempo ir descubriéndolas todas.</p>
<p>Hoy voy a hablar de <a href="http://docs.python.org/library/basehttpserver.html">BaseHTTPServer</a> un módulo de Python 2.x (en 3.x se llama http.server) que nos permite implementar un servidor web en muy pocas líneas de código. Es la base de otros dos módulos muy interesantes, <a href="http://docs.python.org/library/simplehttpserver.html">SimpleHTTPServer</a> y <a href="http://docs.python.org/library/cgihttpserver.html">CGIHTTPServer</a>. El primero implementa un muy simple servidor web que sirve archivos y el segundo es un servidor que ejecuta script CGI en entornos Unix.</p>
<p>Por ejemplo, con SimpleHTTPServer podemos hacer algo tan maravilloso como esto:</p>
<pre>$ cd ~/musica
$ python -m SimpleHTTPServer
</pre>
<p>Y con sólo eso tenemos montado un servidor web escuchando en 0.0.0.0:8000 y sirviendo todos nuestros archivos de la carpeta ~/musica.</p>
<p>Pero la clase BaseHTTPServer es más poderosa porque nos permite implementar nuestros propios RequestHandlers, es decir, clases que extiendan <a href="http://docs.python.org/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler">BaseHTTPRequestHandler</a> y hagan lo que nosotros queramos en cada petición para cada método HTTP. Por ejemplo, para implementar el método GET solamente hace falta crear una clase que extienda BaseHTTPRequestHandler y sobrecargar el método do_GET.</p>
<p>Por ejemplo, si yo quisiera implementar un muy básico servidor que me diga el <a href="http://en.wikipedia.org/wiki/Load_%28computing%29">load average</a> del sistema sería tan sencillo como poner:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="co1"># -*- coding: utf-8 -*-</span><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">BaseHTTPServer</span></p>
<p><span class="kw1">class</span> RequestHandler <span class="br0">&#40;</span><span class="kw3">BaseHTTPServer</span>.<span class="me1">BaseHTTPRequestHandler</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> do_GET <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">send_response</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">end_headers</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">wfile</span>.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">self</span>._get_status<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> _get_status <span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st0">&quot;Status:<span class="es0">\n</span>&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;&#8212;&#8212;-<span class="es0">\n</span>&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Load average: %s<span class="es0">\n</span>&quot;</span> % \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span><span class="st0">&quot;%01.2f, %01.2f, %01.2f&quot;</span> % \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">os</span>.<span class="me1">getloadavg</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p><span class="kw1">def</span> main <span class="br0">&#40;</span>args<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; httpd = <span class="kw3">BaseHTTPServer</span>.<span class="me1">HTTPServer</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&#8216;localhost&#8217;</span>, <span class="nu0">8000</span><span class="br0">&#41;</span>, RequestHandler<span class="br0">&#41;</span><br />
&nbsp; &nbsp; httpd.<span class="me1">serve_forever</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Y al entrar a http://localhost:8000 vería algo así:</p>
<pre>Status:
-------
Load average: 0.26, 0.35, 0.40
</pre>
<p>A esta altura creo que se hace bastante evidente el potencial de esta clase BaseHTTPServer. Piensen lo sencillo que sería hacer un servidor para un <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services">web service REST (RESTful web service)</a> implementando métodos do_GET, do_DELETE, do_POST etc.</p>
<p>Para jugar un poco hice una versión un poco más completa de este servidor de status. Al correrlo lanza el servidor HTTP, al cual podemos acceder para pedirle un status general del sistema en tres formatos: texto plano (plain), HTML y JSON. También le agregué un <a href="http://docs.python.org/library/optparse.html">OptionParser</a> para poder configurar el host y puerto en el cual el servidor deberá escuchar. Con comentarios y todo ocupa 149 líneas.</p>
<p>Pueden ver el código aquí: <a href="http://pastebin.com/G5FgTDiv">http://pastebin.com/G5FgTDiv</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/python-basehttpserver-un-servidor-http-en-unas-pocas-lineas.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ciclo de Charlas Abiertas de Python Argentina en La Tribu</title>
		<link>http://www.tail-f.com.ar/programacion/python/ciclo-de-charlas-abiertas-de-python-argentina-en-la-tribu.html</link>
		<comments>http://www.tail-f.com.ar/programacion/python/ciclo-de-charlas-abiertas-de-python-argentina-en-la-tribu.html#comments</comments>
		<pubDate>Sat, 10 Jul 2010 20:38:07 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Charlas]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=378</guid>
		<description><![CDATA[PyAr,  la comunidad de Python Argentina presenta el Ciclo de Charlas Abiertas de Python 2010 en la sede del Colectivo La Tribu. Se trata de una serie de presentaciones que tendrán lugar los días sábados, a lo largo de la segunda mitad del año, desarrollando distintos temas relacionados con Python desde los más básicos a [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_379" class="wp-caption alignright" style="width: 174px"><a href="http://www.tail-f.com.ar/wp-content/uploads/pyar-logo.png"><img class="size-full wp-image-379" title="Python Argentina" src="http://www.tail-f.com.ar/wp-content/uploads/pyar-logo.png" alt="Python Argentina" width="164" height="65" /></a><p class="wp-caption-text">Python Argentina</p></div>
<p><a href="http://python.org.ar/pyar/Inicio">PyAr</a>,  la comunidad de Python Argentina presenta el <a href="http://python.org.ar/pyar/CharlasAbiertas2010">Ciclo de Charlas Abiertas de Python 2010</a> en la sede del <a href="http://www.fmlatribu.com/">Colectivo La Tribu</a>.</p>
<p>Se trata de una serie de presentaciones que tendrán lugar los días sábados, a lo largo de la segunda mitad del año, desarrollando distintos temas relacionados con <a href="http://www.python.org/">Python</a> desde los más básicos a algunos bastante avanzados. Las charlas estarán a cargo de miembros de la comunidad PyAr, destacados desarrolladores con un profundo dominio del lenguaje en cuestión.</p>
<p>Las charlas comienzan el sábado 24 de julio, su entrada es libre y gratuita (sin necesidad de registrarse) y tendrán lugar en la sede del Colectivo La Tribu, sito en Lambaré 873, Capital Federal [<a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=Lambar%C3%A9+873,+ciudad+de+buenos+aires&amp;sll=37.0625,-95.677068&amp;sspn=47.167389,89.296875&amp;ie=UTF8&amp;hq=&amp;hnear=Lambar%C3%A9+873,+Almagro,+Ciudad+Aut%C3%B3noma+de+Buenos+Aires,+Argentina&amp;z=16">ver mapa</a>].</p>
<p>A continuación una versión resumida del cronograma de charlas. La versión completa con descripciones y horarios pueden consultarla en la <a href="http://python.org.ar/pyar/CharlasAbiertas2010">página de PyAr</a>.</p>
<p><strong>Cronograma</strong></p>
<p><strong>Día 1: Sábado 24 de Julio</strong><br />
Tema: Introducción a la Programación<br />
Disertante: Facundo Batista</p>
<p><strong>Día 2: Sábado 31 de Julio</strong><br />
Tema: Introducción a Python<br />
Disertantes: Tomás Zulberti y Facundo Batista</p>
<p><strong>Día 3: Sábado 21 de Agosto</strong><br />
Tema: Introducción al Desarrollo Web I<br />
Disertantes: Mariano Reingart y Alejandro J. Cura<br />
Tema: FooBar (virtualenv, buildout, nose)<br />
Disertante: Roberto Alsina</p>
<p><strong>Día 4: Sábado 11 de Septiembre</strong><br />
Tema: Introducción al Desarrollo Web II<br />
Disertantes: Mariano Reingart y Alejandro J. Cura<br />
Tema: Django<br />
Disertante: Manuel Kauffman</p>
<p><strong>Día 5: Sábado 25 de Septiembre</strong><br />
Tema: Introducción a las Interfaces Gráficas de Escritorio I<br />
Disertante: Roberto Alsina<br />
Tema: Plone<br />
Disertante: Roberto Allende</p>
<p><strong>Día 6: Sábado 2 de Octubre</strong><br />
Tema: Introducción a las Interfaces Gráficas de Escritorio II<br />
Disertante: Roberto Alsina<br />
Tema: wxPython<br />
Disertante: Mariano Reingart</p>
<p><strong>Día 7: Sábado 30 de Octubre</strong><br />
Tema: Optimizando Python<br />
Disertante: Gabriel Genellina<br />
Tema: PyQt<br />
Disertante: Roberto Alsina</p>
<p><strong>Día 8: Sábado 13 de Noviembre</strong><br />
Tema: Python 3000<br />
Disertante: Facundo Batista<br />
Tema: Twisted<br />
Disertante: Lucio Torre<br />
<strong><br />
Día 9: Sábado 27 de Noviembre</strong><br />
Tema: Taller de Programación de Juegos<br />
Disertantes: Alejandro J. Cura y Hector Sanchez</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/programacion/python/ciclo-de-charlas-abiertas-de-python-argentina-en-la-tribu.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Python: Ver dominios de Apache que más transferencia consumen</title>
		<link>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html</link>
		<comments>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html#comments</comments>
		<pubDate>Thu, 11 Mar 2010 01:47:12 +0000</pubDate>
		<dc:creator>elbarto</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[access_log]]></category>
		<category><![CDATA[log]]></category>

		<guid isPermaLink="false">http://www.tail-f.com.ar/?p=361</guid>
		<description><![CDATA[Hace un rato publiqué un post con un script para ver qué dominios de Apache consumen mayor transferencia. El script en BASH toma unos 7 segundos en procesar 750 archivos de uno de mis servidores. Ahora hice una versión en Python, para la que me dieron algunos consejos los chicos de PyAr, y toma aproximadamente [...]]]></description>
			<content:encoded><![CDATA[<p>Hace un rato publiqué un post con un script para ver <a href="http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/ver-dominios-de-apache-que-mas-transferencia-consumen.html">qué dominios de Apache consumen mayor transferencia</a>. El script en <a href="http://www.tail-f.com.ar/tag/bash">BASH</a> toma unos 7 segundos en procesar 750 archivos de uno de mis servidores. Ahora hice una versión en <a href="http://www.tail-f.com.ar/tag/python">Python</a>, para la que me dieron algunos consejos los chicos de <a href="http://python.org.ar/pyar/">PyAr</a>, y toma aproximadamente 4 segundos en procesar los mismos archivos. Aquí les dejo el código:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#!/usr/bin/env python</span><br />
<span class="st0">&quot;&quot;</span><span class="st0">&quot; Access Log Parser</p>
<p>Parses all the files in a directory<br />
treating them as access_log files<br />
and outputs the list of files sorted<br />
by transfered megabytes. Useful for<br />
identifying heavy users.</p>
<p>Usage:<br />
./access_log_parser.py &lt;base_dir&gt;<br />
base_dir = directory where the access_log files are<br />
&quot;</span><span class="st0">&quot;&quot;</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">time</span><br />
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> itemgetter</p>
<p><span class="kw1">def</span> main <span class="br0">&#40;</span>args<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Main</p>
<p>&nbsp; &nbsp; Main function of the script.<br />
&nbsp; &nbsp; This is where the magic happens.<br />
&nbsp; &nbsp; It takes the script arguments<br />
&nbsp; &nbsp; and returns an exit code.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Parameter checking</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>args<span class="br0">&#41;</span> &lt; <span class="nu0">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Usage: %s &lt;base_dir&gt;&quot;</span> % args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">isdir</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; base_dir = args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">print</span> <span class="st0">&quot;%s is not a directory&quot;</span> % args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> <span class="nu0">2</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Init vars</span><br />
&nbsp; &nbsp; t1 = <span class="kw3">time</span>.<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; mbyte = <span class="nu0">1048576.0</span><br />
&nbsp; &nbsp; domains = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Start processing files</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> item <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; path = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>base_dir, item<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">isfile</span><span class="br0">&#40;</span>path<span class="br0">&#41;</span> <span class="kw1">and</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">getsize</span><span class="br0">&#40;</span>path<span class="br0">&#41;</span> &gt; <span class="nu0">0</span>:</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes = <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init_date = <span class="kw2">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = <span class="kw2">None</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Process file lines</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> line <span class="kw1">in</span> <span class="kw2">open</span><span class="br0">&#40;</span>path, <span class="st0">&#8216;r&#8217;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> init_date <span class="kw1">is</span> <span class="kw2">None</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init_date = data<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += <span class="kw2">long</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="nu0">9</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">ValueError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">pass</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; domains.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#123;</span><span class="st0">&#8216;domain&#8217;</span>: item, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;mbytes&#8217;</span>: bytes / mbyte, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;init_date&#8217;</span>: init_date, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;end_date&#8217;</span>: data<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># Print out sorted information</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> domain <span class="kw1">in</span> <span class="kw2">sorted</span><span class="br0">&#40;</span>domains, key=itemgetter<span class="br0">&#40;</span><span class="st0">&#8216;mbytes&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;%.2f MB | From: %s | To: %s | %s&quot;</span> % \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>domain<span class="br0">&#91;</span><span class="st0">&#8216;mbytes&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;init_date&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;end_date&#8217;</span><span class="br0">&#93;</span>, \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;domain<span class="br0">&#91;</span><span class="st0">&#8216;domain&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Generated in %d seconds&quot;</span> % <span class="br0">&#40;</span><span class="kw3">time</span>.<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> &#8211; t1<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span>main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
<p>Para ejecutarlo:</p>
<pre>./access_log_parser.py /tmp/domain_logs
...
544.30 MB | From: 10/Mar/2010:02:48:33 | To: 10/Mar/2010:18:13:25 | dominio1.com.ar.log
602.34 MB | From: 10/Mar/2010:00:23:09 | To: 10/Mar/2010:23:39:45 | dominio2.com.ar.log
944.03 MB | From: 10/Mar/2010:00:49:35 | To: 10/Mar/2010:23:39:57 | dominio3.com.ar.log
Generated in 3 seconds
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.tail-f.com.ar/servicios/httpd/apache-httpd-servicios/python-ver-dominios-de-apache-que-mas-transferencia-consumen.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

