La información infinita

Ayer me enteré de algo gracias a Internet que desconocía de alguien que conozco. El qué no es importante. Lo importante es que posiblemente hayamos perdido el anonimato. Buscar tu propio nombre en Internet es algo bastante común, que todo el mundo hace de vez en cuando, o eso dicen las estadísticas al menos…  ¡Si hasta puedes hacerte un perfil para que Google sepa qué enseñar cuando la gente te busca!

El caso es que, si nos buscamos, o buscamos a algún amigo de la infancia, posiblemente nos salgan resultados. Y ya sabemos que eliminar un resultado de Internet es algo muy complicado, así que pasados los años podemos tener practicamente nuestra vida. Quizá una entrada en nuestro blog (que ya abandonamos) diciendo que estamos enamorados, otro en el post de una amiga de nuestra ex diciendo lo mal que estámos por haberlo dejado. Unas fotos donde un amigo te ha etiquetado. Unos comentarios en el blog de horticultura, que nos dió por ahí en su momento. Un video en YouTube de cuando hiciste el corto ese en la Universidad…

Y así, pasando el tiempo, tu vida está en la Red. El problema es que es posible que estén las cosas que, bueno, bien te interesa, bien no te importa que estén. Pues igual una foto en la promoción de tu carrera, o haciendo una presentación en un ciclo de conferencias, pero tambien va a estar toda esa información que no quieres que esté. A lo mejor alguien te pone a caer de un burro. O tienes una foto vergonzante que te sacaron. Lo más típico son las fotos de una noche de juerga, pero no está limitado a eso. O a lo mejor, simplemente no te da la gana contar tu vida, porque eres pudoroso y estás harto de que te recuerden la foto vestido de almirante de flota de tu comunión… Quizá la gente de mi edad y mayor tenga siempre oscura su infancia y adolescencia, pero la gente que tiene a día de hoy 13 y 14 años posiblemente tenga siempre ahí esa novia que se echó en el instituto para toda la vida encontrable de alguna manera.

No voy a entrar si es bueno o es malo. Lo que parece es que es inevitable. ¡Estoy convencido de que saldrá dentro de poco un buscador específico para personas, que buscará los rasgos en todas las fotos, correos, nicks y demás! ¿Estaremos condenados toda la vida a estigmatizarnos por un error de juventud? ¿Rezaremos porque nuestro jefe nunca vea las fotos de “esa” juerga? Todo este mundo de información abre las puertas a un nuevo tipo de relaciones personales, donde quizá no juzguemos tanto a la gente por un sólo aspecto de su pasado, si no que seamos capaces de ver más allá. Y posiblemente también tomemos mucha más conciencia de nuestro “posicionamiento en la red”, al menos hacer que nuestros primeros resultados tengan un sentido…

Realmente esto de Internet está cambiandolo todo a pasos agigantados.

PD: ¡He logrado encontrar, rescatado en na cápsula del tiempo, mi antiguo blog WrongSideOfMemphis! El estilo me gustaba más, pero WordPress.com no me deja toquetear mucho con este… De todas formas, intentaré recuperar los artículos antiguos, hay algunos que me gustaría tener por aquí…

Travelling salesman

I'm selling this fine leather jackets
I’m selling this fine leather jackets

One classic computation problem, the travelling salesman. Even if it’s quite simple to describe, it’s one of those hideous NP complete problems, the ones that are quite difficult to resolve, as the computation time needed grows greatly with the length of the data. On Programming Praxis they have proposed to resolve the problem using brute force, and using the closest neighbor (a simplification of the problem).

I’ve created this program, in Python.

import random
import itertools
import operator
import datetime

MAX_X = 100
MAX_Y = 100

def random_cities(number):
    ''' Generate a number of cities located on random places '''

    cities = [ (random.randrange(0, MAX_X),
                random.randrange(0, MAX_Y))
                for i in range(number) ]

    return cities

def path_lenght(path):
    ''' Get the lenght of a path '''
    lenght = 0
    for i in xrange(len(path) - 1):
        # Add the distance between two cities
        lenght += abs(complex(path[i][0], path[i][1])
                       - complex(path[i + 1][0], path[i + 1][1]))

    return lenght

def find_path_bruteforce(cities):
    ''' Find the smallest path using brute force '''

    lenghts = []

    for path in itertools.permutations(cities, len(cities)):
        # Get the length of the path, adding the returning point
        total_path = path + (path[0],)
        lenght = path_lenght(total_path)
        lenghts.append((total_path, lenght))

    # Get minimum
    lenghts.sort(key=operator.itemgetter(1))
    return lenghts[0]

def find_path_nearest(cities):
    ''' Find the closest neibour '''

    lenghts = []
    for city in cities:
        lenght = 0
        actual_cities = cities[:]
        actual_city = actual_cities.pop(actual_cities.index(city))
        path = [actual_city, ]
        # Find nearest neibour
        while actual_cities:
            min_lenght = []
            for next_city in actual_cities:
                min_lenght.append((next_city, abs(complex(city[0], city[1])
                                                 - complex(next_city[0], next_city[1]))))
            # Get closest neibor
            min_lenght.sort(key=operator.itemgetter(1))

            actual_city = min_lenght[0][0]
            lenght += min_lenght[0][1]
            actual_cities.pop(actual_cities.index(actual_city))
            path.append(actual_city)

        # Complete the trip with the first city
        path.append(city)

        lenghts.append((tuple(path), path_lenght(path)))

    # Get minimum
    lenghts.sort(key=operator.itemgetter(1))
    return lenghts[0]

if __name__ == '__main__':
    for i in range(3, 10):
        print 'Number of cities: ', i
        cities = random_cities(i)

        time1 = datetime.datetime.now()
        path2, lenght_neighbor = find_path_nearest(cities)
        time2 = datetime.datetime.now()
        print path2, lenght_neighbor
        time_neighbor = time2 - time1
        print 'Time neighbor: ', time_neighbor

        time1 = datetime.datetime.now()
        path1, lenght_brute = find_path_bruteforce(cities)
        time2 = datetime.datetime.now()
        print path1, lenght_brute
        time_brute = time2 - time1
        print 'Time brute force: ', time_brute
        print 'Diff: ', float(lenght_neighbor - lenght_brute) / lenght_brute * 100, '%'

The time spend on each is brutally different, specially as the number of cities grow. With more than 9 cities, the time grows at some point when my computer has to take more than minutes to compute the brute force approach, while the neighbor approach will still be below the 1/100 of a second. The error  also grows, being the same on small number of cities, but getting afar fast when the number of cities grow. At 9 cities, the error is about a 20-30%

Crítica despiadada de “Todo va a cambiar” de E. Dans

Influido y presionado desde Twitter, he decidido leerme el libro “Todo va cambiar”, de Enrique Dans. Sinceramente, ha sido un suplicio, y la idea es hacer un resumen para que nadie más tenga que hacerlo… 😀

Primero, unas ideas preconcebidas. No me gusta nada Enrique Dans. Lo encuentro el paradigma del gurú de Internet que simplemente habla sin tener mucha idea, que intenta comunicar a base de repetir las mismas ideas que hacen otros, y con un sobramiento de sí mismo desmesurado. Hay un lugar para “los comunicadores”, gente que se encarga de recopilar ideas y darles un tratamiento único. Hacerlo bien es difícil y hay que reconocerlo. Hay otros que se dedican a poco menos que copipegar todas las ideas que pueden, y encima lo cuentan peor que el original. Eso sí, parece que es una especie de gurú del 2.0 y que tiene muchos seguidores. Pues vale.  El que espere una crítica amable, puede dejar de leer 😀

Dicho mis ideas generales sobre Enrique Dans, vamos a lo que es el libro. En general, me resulta un libro prescindible e infumable (que es todavía peor). Principalmente se dedica a recopilar ideas muy manidas, a saber: Web 2.0 bueno. Derechos de autor, malo. Nuevos paradigmas. Compañías que no evolucionan. Google bueno, Microsoft, malo.Todo esto aderezado con un estilo de escribir aburrido y pagado de sí mismo, con contínuas referencias personales un poco metidas con calzador.

Creo que lo peor que tiene el libro es que su concepto debería ser algo que inspirase, que te animase a hacer algo, pero el 90% del tiempo está comentando los mismo ejemplos de siempre (Amazon, eBay, Google, Microsoft, etc), y no resulta inspirador. Comparado con, por ejemplo, Seth Godin, se le ven las carencias. Por ejemplo Brainwashed (traducido al español en el blog Desencadenado) o Bootstrapper Bible son buenos textos que te impulsan a pensar, a cargar las pilas, a intentar hacer algo… El que Enrique Dans te cuente sus batallitas de pionero internauta, pues no te da el mismo impulso… Así que tenemos dos opciones: O bien lo que dice el libro te lo sabes y ya lo has hecho (ya has cambiado) o bien, si no lo sabes, le falta la parte de verdaderamente animar a hacer algo. Por eso digo que es prescindible.

Aun así, hay libros prescindibles y animados de leer, que aumentan tus conocimientos. No es el caso, el estilo (al menos a mí) me resulta soporífero y cada pocas páginas tengo que darme de cabezazos por alguna metedura de pata o algunas de sus “perlas”. Además, se hace difícil para el profano al ahondar en términos excesivamente técnicos, y los pocos que se explican se hacen de manera bastante farragosa. Curiosamente, para ser un “libro 2.0”, es raro que no incluya enlaces y referencias a muchas páginas para apreder más. Si me da por pensar mal, será para que no se noten las carencias.

Para los que no tienen ganas de leerse el libro (y, desde aquí, no se lo recomiendo a nadie), he decidido hacer un resumen, capítulo por capítulo con las cosas más cargantes que aparecen…

  • Después de un prólogo firmado por Vint Cerf, con sobreabundancia de términos técnicos en inglés y entiendo que fuera de lugar para un libro “generalista” (sospecho que se escribió en inglés), viene la introducción. sin duda, una de las joyas del libro, que relata las maravillosas aventuras de un pionero, un visionario en esto de los ordenadores, un gurú. Claro que sus “visiones” producen más risa que otra cosa a cualquiera que haya estado relacionado con ordenadores los últimos 15 años, pero bueno. Al tratarse de un tema “cercano”, el estilo es menos “plomizo” (comparado con el resto del libro), pero mucho más “sobrado”.
  • Música, películas, mentiras e Internet. El primer capítulo es una sucesión de topicazos, argumentos mil veces repetidos ya hace años, y aderezados con una serie de pedantes referencias históricas. Los argumentos son los de siempre sobre el tema copyright, y es un tema taaaan manido. David Bravo explica lo mismo de manera muchísimo más amena (y hace 5 años) en “Copia este libro”
  • Las evidencias del cambio. Explicando las bondades del software libre y cómo la Wikipedia es mucho mejor que la Enciclopedia Británica (entre otros ejemplos de cómo la tecnología mejora nuestras vidas, con ejemplos). Tampoco escatima en poner por las nubes a su padre y abuelo, pero incluso ellos tendrían problemas con los cambios. Y pensar que mi abuelo usaba un ordenador e Internet, siendo una de las personas más negadas para temas técnicos que he conocido… Pero el gran descubrimiento del capítulo es el hecho de que la palabra “Viagra” se puede deletrear de 600.426.974.379.824.381.952 (son 21 cifras) de manera que sea reconocible por los humanos. Viene de este artículo, que obviamente, es más una broma que otra cosa… Entre otras cosas, porque acepta cosas como “aVbIPARGIRNam” como una forma de deletrear “Viagra” de manera (perfectamente) reconocible por los humanos… Sin embargo, creo que es un gran número para definir el ego de Enrique Dans en relación al ego de una persona normal, es decir, su ego es 600.426.974.379.824.381.952 veces superior al de una persona normal, o 1 edans veces…
  • La disrupción tecnológica (cuando lo vemos venir). Habla de lo rápido que pueden darse procesos de cambio. También tiene “detalles”, “los productos bit” y “los productos átomo”, que viene siendo “información” y “cosas físicas”, claro que dicho así resulta menos lioso y Enrique Dans dice textualmente: “Pero nadie le dijo que la lectura de este libro iba a ser fácil”. Creo que debería ir en la contraportada, a modo de advertencia. Otro detalle: “cuando llegué en 1996 a los Estados Unidos tras haber recibido durante toda mi vida una educación en inglés británico, el acento californiano me suponía ciertos problemas de comprensión”. Si escribe eso, o no ha hablado con un británico en su vida (supongo que con algún californiano sí) o se las da de que sabía inglés británico mejor que la Reina antes de llegar a California.
  • La evolución de la comunicación. Básicamente una evolución, desde nuestros ancestros comunicándose a base de aullidos, hasta los blogs. Curiosamente, no comenta nada específico de Twitter o Facebook.
  • Introducción a la red. La neutralidad de la red. Resume la idea de la neutralidad de la web y cómo “oscuros intereses” pueden interferir, junto a ideas como que es un derecho, etc…
  • Los costes de transacción y comunicación. O cómo las empresas “antiguas” tendían a crecer verticalmente (llevando el control de producto desde la materia prima hasta la venta al por menor) y ahora se tiende a especializarse y a poder trabajar repartidos por el mundo. Deja claro que conoce bien cómo funciona Weblogs SL.
  • La generación perdida: La resistencia a la tecnología. Los típicos comentarios de que Internet es fabulosa y en España tiene muy mala prensa. Que hay sitios peligrosos, pero no es para tanto, y que las empresas tienen que adaptarse y no rechazar los cambios tecnológicos, o serán aparcadas. Otra vez, nada nuevo.
  • Una nueva generación. Lecciones sobre cómo educar a tus hijos en la tecnología. Me parece un capítulo especialmente peligroso (y posiblemente polémico), ya que diserta sobre el uso de las tecnologías en niños y adolescentes, resumido en “los niños utilizan de manera más natural las redes sociales y saber usarla mejor” y critica cosas como el uso de filtros o restricciones el uso de los ordenadores en niños. Me parece peligroso porque entra en un terreno sumamente resbaladizo, como es la educación de los hijos, y evita el siguiente problema. Si el padre sabe poco o nada de Internet, ¿cómo debe educar a su hijo al respecto? No es nada fácil responder a estas preguntas, incluso por (verdaderos) expertos, pero Enrique Dans sienta cátedra con una rotundidad bestial.
  • La red y el neohumanismo. Aparentemente, vivimos en sociedades en las que la identidad individual ha sido cercenada. Y sólo lo recuperaremos por Intenné. O eso dice. A mí me parece una tontería como un castillo, será que no soy un gurú que marca tendencias. Y volvemos a la idea de que no eres nadie si no estás en Google posicionado como un experto. Chorrisandeces de esas que Andrés, en Marca Propia, se encarga de desmontar todos los días. El mundo no es sólo Internet (y lo dice alguien que trabaja en el ramo y para quien Internet es MUY importante).
  • Un caso práctico: Microsoft. Hacer leña del arbol caído siempre es interesante, y Microsoft es una compañía que se presta como pocas a calificarla como “el Mal Absoluto”. Pero de ahí a contar la historia de Microsoft como se cuenta en este capítulo, hay un mundo. Porque se dedica, básicamente, a ponerlos a caer de unburro, relativizar sus éxitos y ahondar en sus fracasos. Además, nos volvemos a encontrar “perlas” de las que me llama la atención esta: “Los mejores lenguajes de programación son PHP, Perl o Python.” Vamos, que nos tomamos muy a pecho las arquitecturas LAMP (también hace referencia a Apache) 😀 Resultado, “Microsoft es la historia de una falta de adaptación”. Y mira que Python es mi lenguaje de programación favorito 😉
  • La evolución de la web. Varios ejemplos de empresas exitosas en Internet, como Google, Amazon, YouTube o eBay. Los ejemplos de siempre, vamos.
  • Un caso práctico: Google. En comparación con el anterior, todo loas a Google. Algunas explicaciones de cómo funciona su buscador (aunque pasa de puntillas frente a otras alternativas que había, en su momento y califica a Yahoo de “directorio”), y, curiosamente, una reseña sobre el tema de la privacidad, que se salda diciendo que Google “es muy transparente” y que en cualquier momento podemos borrar las cookies del navegador…
  • La evolución de la tecnología: del ordenador a la nube. Cambiar de un procesador de textos con datos en local, a “la nube”, ese concepto etéreo que parece que las cosas no se guardan en ningún sitio, pero están muy seguras. Aviso a navegantes, procurad tener copia de las cosas realmente importantes que tengais en la nube. Ningún sistema es seguro al 100%
  • Nuevas herramientas para nuevos escenarios. ¿Slashdot es un blog? Este capítulo trata sobre lo guays que son los blogs y lo fácil que es escribir en uno y hacerse un reputado experto y gurú. Además de algunas reseñas a Twitter y a Digg.
  • La sociedad hiperconectada. Blogs (de nuevo), comentarios, twitter, respuestas de las empresas a usuarios que se quejan en Internet, comunidades, trolls interneteros… Tiene pinta de repetición de otras fuentes, a veces está deslavazado y repite machaconamente ideas de otros capítulos como “El efecto Streissan”.
  • Revisando los papeles: Participación y comunidades. ¡Móntese un blog si no lo tiene! Es muy importante, pero si lo abandona, nadie le echará de menos…
  • El futuro. Aquí Enrique Dans nos obsequia con lo guay que es su vida con el uso de la tecnología y cómo podremos disfrutar de parte de ella si nos conectamos a Internet, participamos, compramos y hacemos nuestra vida más tecnológica… Las gestoras de derechos seguirán luchando por conservar el poder e impedir el libre intercambio de archivos. Las telefónicas querrán no ser neutrales. Los “viejos poderes” intentarán impedir los derechos digitales, pero no podrán. Todos podremos ser creadores y se democratizará la creación. Se eliminarán intermediarios. El mercado se fragmentará aún más y habrá un nuevo modelo económico. Todo ha cambiado ya. Si no has oído música de violines al leer esta parte y has aplaudido al final, es que ya has oído lo mismo desde hace unos 10 años mil y una veces… Yo al menos, exijo que se narre con garra…

En resumen, me ha parecido infumable. No sólo habla de los mismos (y típicos) ejemplos una y otra vez, sino que lo plaga de referencia que oscilan entre lo irrelevante y lo pedante, y el autobombo más descarado. El libro es aburrido, lleno de términos desconocidos para el que no está pendiente de la informática e irrelevancias para el que está pendiente.

Interesting Project Euler problem

There is one interesting problem to solve from the guys on Project Euler.

I think that maybe there are some problems running a naive approach to the problem on the 2002, but right now, even a inefficient approach can give you results in not much time. I’ve made the following program in Python to measure the differences between a straight approach, and one using recursion and memoization. Looking carefully at the sequences, we realize that each time we get to a previous calculated number, we don’t have to recalculate the sequence again. So, doing it by hand, for the numbers from 1 to 5:

1 : 1 step
2 --> 1 : 2 steps
3 --> 10 --> 5 --> 16 --> 8 --> 4 --> 2 --> 1 : 8 steps
4 --> 2 --> 1: 3 steps (note that is repeated from below)
5 --> 16 --> 8 --> 4 --> 2 --> 1 : 6 steps (again, is repeated)

So, by memoization, we can store the length of previous results, so we don’t have to calculate them again.

from datetime import datetime
import operator

def inneficient(number):
    ''' Find the number of steps to 1, inefficiently '''
    steps = 1

    while number != 1:
        if number % 2 == 0:
            number = number / 2
        else:
            number = number * 3 + 1
        steps += 1

    return steps

numbers = {1:1}
def efficient(number):
    ''' Find the number of steps to 1, nefficiently '''

    if number in numbers:
        return numbers[number]
    else:
        if number % 2 == 0:
            result = efficient(number / 2) + 1
        else:
            result = efficient(number * 3 + 1) + 1
        numbers[number] = result

        return result

def inefficient_search(times):
    return max(((number, inneficient(number)) for number in xrange(1, times + 1)), key=operator.itemgetter(1))

def efficient_search(times):
    return max(((number, efficient(number)) for number in xrange(1, times + 1)), key=operator.itemgetter(1))

def execute(function, times):
    time1 = datetime.now()
    result = function(times)
    time2 = datetime.now()
    total_time = time2 - time1
    print '{0:18}: {1:9} times, time {2}. Result: {3}'.format(function.__name__, times,
                                                              total_time, result)

def main():
    ''' Find the longest secuence of numbers '''
    SMALL_NUM = 1000
    BIG_NUM = 1000000

    execute(inefficient_search, SMALL_NUM)
    execute(efficient_search, SMALL_NUM)

    execute(inefficient_search, BIG_NUM)
    execute(efficient_search, BIG_NUM)
    # Add another result, even bigger, to show that the complexity of the problem is not linear
    execute(efficient_search, BIG_NUM * 10)

if __name__ == '__main__':
    main()

And the results on my computer:

inefficient_search:      1000 times, time 0:00:00.022727. Result: (871, 179)
efficient_search  :      1000 times, time 0:00:00.002074. Result: (871, 179)
inefficient_search:   1000000 times, time 0:00:31.148715. Result: (837799, 525)
efficient_search  :   1000000 times, time 0:00:01.822361. Result: (837799, 525)
efficient_search  :  10000000 times, time 0:00:18.398862. Result: (8400511, 686)

So even the first option doesn’t take too long to run on a modern computer, although, of course, the second one is much faster.

PD: I get to this problem after this post from the blog of S. Lott. Includes a funny cartoon!

Deployment of Django project using CherryPy and Cherokee

Recently, we have deployed into a test production our latest Django project. Choosing which deployment to use it’s not easy, as there are a lot of different tools for the job, but as we expect some load on the system, we have been spending some time in getting a good deployment that will allow us to be confident on the grow of the system.

After some research, we decided to use CherryPy and Cherokee.

Why CherryPy?

  • It’s pure Python, and easily integrated with Django. You can do it by yourself (it’s not very difficult), or you can take the easy way and use the django-cpserver tool. Anyway, we probably will end up customizing django-server to suit your needs, as there are some things that seems to be lacking (like logging support)
  • It’s fast! Also it’s mature and stable. All three are must-have characteristics for any web server.

Why Cherokee?

  • Its admin system. It’s really easy to use (instead of the usual .conf file, which can be a headache) and also quite safe, as it will only be active when a command is called, with a one-time-only password. It’s a great feature!
  • It allows us to make our deployment. It’s described bellow. Basically, we are using it as a HTTP reverse proxy that will balance the load between several CherryPy instances. It will also serve our static files.
  • Low memory footprint.
  • Cherokee is able to manage all the CherryPy processes, so you don have to worry about launching and controlling them. You don’t have to daemonize the CherryPy processes also, making all the process much easier.
  • It’s blazingly fast! It’s specially good serving static files. The speed is in the same league than ngix.

Not everything is great. We have also some problems, already solved or that will be solved in the future.

  • As I said, django-cpserver doesn’t allow you to specify logging parameters to CherryPy. We will have to tweak it, although this is not difficult.
  • We have a problem with this configuration with CherryPy 3.1 Ocasionally, when you ask for a page in Chrome or IE (but not in Firefox), you’ll get a blank page and a 408 error (request timeout). This will indicate that the connection between the client and the server has been lost, and it’s happening only when the option Keep Alive in the Cherokee server is activated. Asking for the page again will reload the data, as a new connection will be open. Apparently, this was due a bug in CherryPy that has been corrected in version 3.2 (which is now on Release Candidate state). Version 3.2.0RC1 seems to work perfectly fine.

Our deployment configuration is described in the following diagram.

Architecture

The static data is directly served by Cherokee, while the Django application is supported by CherryPy. There are several processes of Django-CherryPy working, one of each core the server has, to increase the response avoiding problems with the GIL working over multiple cores, as well as making the architecture much scalable. Cherokee is conecting to the CherryPy instances over TCP/IP, so it gives quite flexibility. It’s also possible to use a Unix domain socket path, which could be even (a little) faster. As Cherokee allow to define an Information Source as a local interpreter command, you just write an script creating a new CherryPy instance, and Cherokee will manage to set up the processes and to kill everything when you stop the server. Cool.

We have also used memcached to increase the response of Django. It’s quite easy to use. Just install memcached on the machine, python-memcached to allow Python access it, and with a few configuration touches on your settings.py file, you’re ready. At the moment, as our views won’t change often, our approach is to use the @cache_page decorator, to cache completely the view. We’re not caching the complete site as that will not cache everything that gets URL parameters, which we’ve been using for generic_views.

All the architecture is highly scalable. Right now everything is on the same machine, but can be spread on different machines. Each process (Cherokee, CherryPy instances and Database) can be separated without much effort. Also, more instances of Django+CherryPy can be created. The only part that can be difficult to duplicate is the Cherokee server, but it’s difficult it will come to be the bottleneck of the system, unless the system grows REALLY big.

The system seems to be really fast and we’re having great testing results for the moment. In a couple of weeks the system is supposed to be public, and we expect quite a lot of hits, so performance it’s quite important, but, for the moment, we are quite satisfied with our deployment.

PD: For a tutorial on configuring Cherokee and CherryPy, you could check this great post.

Store standard output on a variable in Python

This is a great, hacky trick to get the standard output ( and others like standard error and standard input) in Python

You can “redirect” the standard error changing the sys.stdout module with your own StringIO object. So, you can do something like


from StringIO import StringIO  # Python2
from io import StringIO  # Python3


import sys

# Store the reference, in case you want to show things again in standard output

old_stdout = sys.stdout

# This variable will store everything that is sent to the standard output

result = StringIO()

sys.stdout = result

# Here we can call anything we like, like external modules, and everything that they will send to standard output will be stored on "result"

do_fancy_stuff()

# Redirect again the std output to screen

sys.stdout = old_stdout

# Then, get the stdout like a string and process it!

result_string = result.getvalue()

process_string(result_string)

Easy and very useful!

 

EDITED: Updated to make it work for Python 3.4