Implementación de un sistema de cómputo Map-Reduce sobre AMQP

 

Para el cierre de la materia de de “Aprendizaje automático sobre grandes volúmenes de datos“, se me ocurrio que seria interesante la creación de una infraestructura “a la hadoop” en puro Python y sobre AMQP. Bueno hice eso y el resultado lo pueden ver acá: http://poopy.jbcabral.org

Además del código presente un informe de como encare el proyecto que esta disponible acá: https://bytebucket.org/leliel12/bigdata_famaf/raw/tip/poopy/build/latex/poopy.pdf

Creo que el informe es bastante ideal para el que quiera entender AMQP o los conceptos muy básicos de Hadoop desde AMQP

Leer Más

PEP 8 – Un capricho

Hoy me dijeron que la guía de estilos de Python es solo “estilo” y no es importante para enseñar a programar a estudiantes

bueno… NO. (por que: es un lenguaje de programación dinámico, anteriormente había caos en el mundo pythonico, hay mucha convención en el código python, y leer código es parte importante de aprender a programar)

Los invito a los jr en Python que piensen eso que copien el siguiente código y lo hagan andar :)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Cls(object):

    def __init__(self):
        a = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed" 
            "diam nonumyeirmod tempor invidunt ut la"
        self.attr_0 = 0
        self._attr_1 = 1
        self.__attr_2 = 3

    def __m0__(self):
        a = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed"  
            "diam nonumyeirmod tempor invidunt ut la"
        return "ok"

    def _m1(self):
        return "ok"

    def __m2(self):
        return ok

inst = Cls()
print inst.attr_0
print inst._attr_1
print inst._Cls__attr_2
print inst.__m0__()
print inst._m1()
print inst.__m2()


Leer Más

Prompt para desarrolladores multi-scm (upgraded)

Encontre este post: http://gepatino.blogspot.com.ar/2013/01/prompt-para-desarrolladores-multi-scm.html (GRACIAS GABRIEL)

Y agregue el soporte para banchs de mercurial. UPDATE: separe svn y bazar para que funcione mejor

PS1='${debian_chroot:+($debian_chroot)}[\033[01;32m]u@h[\033[01;34m] w[\033[01;33m]$(get_repo_info) [\033[01;34m]$ [\033[00m]'

function get_repo_info {
    INFO=""
    DIRTY=""

    if [ "$INFO" == "" ] && [ `svn info 2> /dev/null | wc -l` -gt 0 ]
    then
        [ `svn status 2> /dev/null | grep -v '?' | wc -l` -gt 0 ] && DIRTY='*'
        INFO="⚡svn$DIRTY"
    fi

    if [ "$INFO" == "" ] && [ `bzr info 2> /dev/null | wc -l` -gt 0 ]
    then
        [ `bzr status -S 2> /dev/null | grep -v '?' | wc -l` -gt 0 ] && DIRTY='*'
        INFO="⚡bzr$DIRTY"
    fi

    if [ "$INFO" == "" ] && [ `hg branch 2> /dev/null | wc -l` -gt 0 ]
    then
        BRANCH=`hg branch 2> /dev/null`
        [ `hg status 2> /dev/null | grep -v '?' | wc -l` -gt 0 ] && DIRTY='*'
        INFO="⚡hg:$BRANCH$DIRTY"
    fi

    if [ "$INFO" == "" ] && [ `git branch 2> /dev/null | wc -l` -gt 0 ]
    then
        BRANCH=`git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* (.*)/1/"`
        [ `git status --porcelain 2> /dev/null | wc -l` -gt 0 ] && DIRTY='*'
        INFO="⚡git:$BRANCH$DIRTY"
    fi

    echo $INFO
}

Agregan eso a su ~.bashrc y van a ver algo como esto:

2013-01-12-000458_660x177_scrot

PD: si alguien se anima a seguir por branch de bazar aca hay un codebase
http://blog.grahampoulter.com/2011/09/show-current-git-bazaar-or-mercurial.html

Leer Más

Snippet para usar un unittest bottle.py con un proceso separado

Necsitaba probar un api rest y se me ocurrio levantar bottle en un proceso separado dentro de un testcase; y necesite hacer todos este chicle.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# "THE WISKEY-WARE LICENSE":
# <jbc.develop@gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a WISKEY in return Juan BC

import multiprocessing
import urllib2
import unittest

import bottle

class BottleTest(unittest.TestCase):

    def setUp(self):
        self.process = multiprocessing.Process(
            target=bottle.run,
            kwargs={"port": "8081"}
        )
        self.process.start()

        # wait until bottle process full started
        # si no ponen esto el testcase se va a ejecutar antes
        # que bottle este listo para recibir peticiones
        started = False
        while not started:
            try:
                urllib2.urlopen("http://127.0.0.1:8081/")
            except urllib2.HTTPError:
                started = True
            except urllib2.URLError as err:
                if err.reason.args[0] == 111:
                    pass
                else:
                    raise err
            else:
                started = True

    def tearDown(self):
        self.process.terminate()

    def test_something(self):
        pass

Leer Más

dPaste.com “API”

“API” for http://dpaste.com/

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# THE WISKEY-WARE LICENSE
# -----------------------
#
# "THE WISKEY-WARE LICENSE":
# <jbc.develop@gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a wiskey in return JuanBC
#

# ==============================================================================
# DOC
# ==============================================================================

"""A Simple Client for http://dpaste.com/

"""

# ==============================================================================
#
# ==============================================================================

__author__ = "JuanBC"
__mail__ = "jbc.develop@gmail.com"
__version__ = "0.1.1"
__license__ = "WISKEY_WARE"
__date__ = "2011/11/14"


# ==============================================================================
# IMPORTS
# ==============================================================================

import os
import urllib
import urllib2


# ==============================================================================
# CONSTANTS
# ==============================================================================

DPASTE_URL = "http://dpaste.com/"

FORMAT_2_EXT = {
    "Python": ["py", "pyw"],
    "PythonConsole": [],
    "Sql": ["sql"],
    "DjangoTemplate": [],
    "JScript": ["js"],
    "Css": ["css"],
    "Xml": ["xml"],
    "Diff": ["diff"],
    "Ruby": ["rb"],
    "Rhtml": ["rhtml"],
    "Haskell": ["hs"],
    "Apache": [],
    "Bash": ["sh"],
    "Plain": ["txt"]
}

EXT_2_FORMAT = {}
for k, vs in FORMAT_2_EXT.items():
    for v in vs:
        EXT_2_FORMAT[v] = k

# ==============================================================================
# FUNCTIONS
# ==============================================================================

def filename2format(filename):
    """Retrieves the format of a given filename

    """
    basename = os.path.basename(filename)
    if "." in basename:
        ext = basename.rsplit(".", 1)[1].lower()
        return EXT_2_FORMAT.get(ext, "Plain")
    return "Plain"


def paste(source, file_format="Plain", title="", poster=""):
    """Paste a given source code into dpaste.com with a given format

    """
    file_format = "" if file_format == "Plain" else file_format
    data = urllib.urlencode({"content": source,
                             "language": file_format,
                             "title": title,
                             "poster": poster})
    conn = urllib2.urlopen(DPASTE_URL, data)
    return conn.geturl()


def copy(dpaste_id):
    """Retrieve a code from a given dpaste id

    """
    return urllib2.urlopen(DPASTE_URL + str(dpaste_id) + "/plain").read()


# ==============================================================================
# MAIN
# ==============================================================================

if __name__ == "__main__":
    print(__doc__)

Leer Más

Pycante 0.2.1c

Actualicé Pycante el proyecto que ayuda a utilizar de manera cómoda los archivos “.ui” de QtDesigner  los cambios principales son:

  • El proyecto ahora es BEER-WARE… osea es mas libre que antes
  • No esta mas disponible la función “run”, ahora hay que crear la aplicación desde Qt.
  • Ahora hay una función “EDir” que recibe por parámetro un path de un directorio y retorna una función “E” que apunta al mismo (por ejemplo si tenemos todos nuestros archivos “.ui” en /home/tito).
  • La operatoria con files y widgets no cambia con los EDir.

Ejemplos:

import sys

import pycante

from PyQt4 import QtGui

# CONSTANTS
UI = pycante.EDir("path/to/all/my/ui/files/")

# using path "path/to/all/my/ui/files/file.ui"
class Window(UI("file.ui")):

    def on_buttonBox_accepted(self):
        # buttonBox exist inside file.ui
        ...

app = QtGui.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

Para instalar:

$ pip install pycante

o

$ easy_install pycante

o bajarlo de aca: https://bitbucket.org/leliel12/pycante/

Disclaimers:

  • Lo hice por una necesidad muy puntual
  • El codigo de “W3″ no lo probe aunque puede usarse asi pycante
  • Como notaran en ni un momento llame a SetupUi()… eso pycante lo hace solo.


				

Leer Más

Buscaminas Programming Challenges de la UTN-FRC en Python

Resolví 2 problemas basados en el buscaminas en Python para la competencia de programación de la UTN-FRC, aca esta el código y mas abajo esta un link al repo de mercurial para quien desee bajar el código mas la entrada.

Problema Fácil (Enunciado)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# "THE BEER-WARE LICENSE" (Revision 42):
# <jbc.develop@gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return Juan BC

#===============================================================================
# DOCS
#===============================================================================

"""Solucion al problema del buscaminas para la competencia de programación de la
UTN-FRC.

Objetivo: Ser legible y servir de instroduccion a python

Problema originalmente propuesto:

http://www.programming-challenges.com/pg.php?page=downloadproblem&probid=110102&format=html

Nota se simplifico para trabajar solo con matrices cuadradas

"""

#===============================================================================
# META
#===============================================================================

__author__ = "Juan BC"
__license__ = "BeerWare"
__date__ = "2011/10/26"
__version__ = "0.1"
__email__ = "jbc.develop@gmail.com"
__homepage__ = "http://jbcabral.wordpress.com/"
__twitter__ = "@juanbcabral"

#===============================================================================
# FUNCTIONS
#===============================================================================

def read_n_lines(n):
    """Esta funcion lee las siguientes n linea de la entrada y las retorna
    como una lista de listas.

    """
    lines = []
    for _ in range(n):
        line = list(raw_input())
        lines.append(line)
    return lines

def increment(board, row, col):
    """Funcion de soporte para resolve que incrementa en uno todas los vecinoa
    a una mina

    """
    for row_d in (-1, 0, 1):
        for col_d in (-1, 0, 1):
            rowp = row + row_d
            colp = col + col_d
            if rowp < 0 or colp < 0 
               or rowp >= len(board) or colp >= len(board[rowp]) 
               or board[rowp][colp] == "*":
                continue
            if board[rowp][colp] == ".":
               board[rowp][colp] = 0
            board[rowp][colp] += 1

def resolve(board):
    """Itera sobre cada celda y si encuentra una mina (*) incrementa todos
    sus cacilleros vacios en 1

    """
    for idx_row, row in enumerate(board):
        for idx_col, cell in enumerate(row):
            if cell == "*":
                increment(board, idx_row, idx_col)

def main():
    field = 0;
    while True:

        # leemos el tamaño de nuestro board
        n = int(raw_input())

        # si el tamaño de nuestro board es 0 salimos
        if n == 0:
            break

        # incrementamos el numero de field
        field += 1

        # leemos el tablero
        board = read_n_lines(n)

        # resolvemos el tablero
        resolve(board)

        # armamos la salida
        out = "n".join(["".join([str(c) for c in row]) for row in board])

        # imprimimos la salida con su decoradores
        # y si queda algun "." lo reemplazamos por un cero
        print "Field #{0}:".format(field)
        print out.replace(".", "0")
        print ""

#===============================================================================
# MAIN
#===============================================================================

if __name__ == "__main__":
    main()

Problema Menos Fácil (Enunciado)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# "THE BEER-WARE LICENSE" (Revision 42):
# <jbc.develop@gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return Juan BC

#===============================================================================
# DOCS
#===============================================================================

"""Solucion al problema del buscaminas para la competencia de programación de la
UTN-FRC.

Objetivo: Ser legible y servir de instroduccion a python

Problema originalmente propuesto: http://acm.tju.edu.cn/toj/showp1330.html

"""

#===============================================================================
# META
#===============================================================================

__author__ = "Juan BC"
__license__ = "BeerWare"
__date__ = "2011/10/26"
__version__ = "0.1"
__email__ = "jbc.develop@gmail.com"
__homepage__ = "http://jbcabral.wordpress.com/"
__twitter__ = "@juanbcabral"


#===============================================================================
# FUNCTIONS
#===============================================================================

def read_n_lines(n):
    """Esta funcion lee las siguientes n lineas del file pointer

    """
    lines = []
    for _ in range(n):
        line = list(raw_input())
        lines.append(line)
    return lines

def touch2coordinates(touch):
    """Combierte los "toques" a una lista de coordenadas (fila, columna)
    donde se toco.

    """
    coords = []
    for idx_row, row in enumerate(touch):
        for idx_col, cell in enumerate(row):
            if cell == ".":
                continue
            coords.append((idx_row, idx_col))
    return coords

def coord2mine(row, col, board):
    """Retorna un "*" si el lugar donde indica la cordenada tiene una mina
    en caso contrario retorna cuantas minas rodean a ese lugar.

    """
    # primero nos fijamos en el lugar
    if board[row][col] == "*":
        return "*"
    # sino exploramos
    mines = 0
    for row_d in (-1, 0, 1):
        for col_d in (-1, 0, 1):
            rowp = row + row_d
            colp = col + col_d
            if rowp < 0 or colp < 0 
               or rowp >= len(board) or colp >= len(board[rowp]):
                continue
            if board[rowp][colp] == "*":
                mines += 1
    return str(mines)

def main():
    """Lee desde un archivo un tablero y toques del buscaminas. Por defecto
    usa la salida estandar.

    """
    # leemos
    n = int(raw_input())
    board = read_n_lines(n)
    touchs = read_n_lines(n)

    # resolvemos
    for row, col in touch2coordinates(touchs):
        symbol = coord2mine(row, col, board)
        touchs[row][col] = symbol

    # convertimos a string para imprimir por pantalla
    print "n".join(["".join(1) for row in touchs])

#===============================================================================
# MAIN
#===============================================================================

if __name__ == "__main__":
    main()

Los archivos en formato archivo

Leer Más

Jugando con archivos FLV

Por cuestiones laborales tuve que jugar con archivos flv asi que dejo por aca dos comandos útiles

Para pegar dos videos
mencoder -of lavf -oac copy -ovc copy -o [salida] [entrada0 entrada1 ..., entradaN]

Para Cortar un cacho de video

ffmpeg -sameq --ss [hh:mm:ss.mmmm] -t [hh:mm:ss.mmmm] -i [input_file] [output_file]
  • ss: desde
  • t: hasta

Leer Más

BeerWare

Sencillamente encontré una licencia que me gusta mas y es mas simple  la “BeerWare” 

Mis siguientes fuentes van a venir con la siguiente leyenda:

# "THE BEER-WARE LICENSE" (Revision 42):
# <jbc.develop@gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return Juan BC

Leer Más