Python R2


Usar los template ya hechos en Sigma en Python

Posted in Python por Arturo Elias Antón en 19 septiembre 2008
Tags: , , , ,

En estos días tuve que migrar todo un código PHP a Python.
Este sistema hecho en PHP, ya tenía todos los template HTML hechos en Sigma.
Como no encontré ningún sistema de template de python compatible con Sigma, hoy me puse a hacer uno.

Ejemplo

Template:
ejemplo.htm

<html>
<head>
</head>
<body>

{prueba1}
<h1>{prueba2}</h1>
<!-- INCLUDE ejemploSub.htm -->
</body>
</html>

ejemploSub.htm

<table>
<!-- BEGIN fila -->
<tr>
    <!-- BEGIN columna -->
    <td>
	    <input type="text" value="{dato1}"/>
    </td>
    <!-- END columna -->
</tr>
<!-- END fila -->
</table>

Codigo:

#!/usr/bin/python
from binsdWeb import *
import sys

strTemplate =sys.argv[0].split(".")[0]+".htm"
fileTemplate = file(strTemplate)

template = binsdTemplate.BinsdTemplate("1",fileTemplate.read())
template.addBlock("ejemploSub")

for i in range(5): #recorro del 0 al 4 para formar  5 filas
    template.ejemploSub1.addBlock("fila")
    template.ejemploSub1.fila[i].addNumBlock("columna",4)     #<---|
    for j in range(4): # recorro del 0 al 3 para formar 4 filas----|
        template.ejemploSub1.fila[i].columna[j].dato1 = str(i)+"-"+str(j)

print "Content-Type: text/html"
print ""
print """\
"""
print template.printTemplate()

Me gustaría aclarar que donde dice ” template.ejemploSub1″ podría haber dicho ” template.ejemploSub[0]” y tendríamos el mismo resultado.  ya que tanto los bloques, como los include, pueden ser referenciados por medio del subíndice de la lista que van de 0 a n, o por medio de la propiedad, que tendrá el mismo nombre del bloque o include, mas un índice de 1 a n.

Si alguien necesita una ayuda solo escríbame y le mandare más info. Para bajar el paquete con ej ejemplo aca esta el link http://www.binsd.com.ar/binsdWeb/binsdWeb.rar

y para ver correr el ejemplo http://www.binsd.com.ar/binsdWeb/ejemplo.py

De todos los sistemas de template que me recomendaron uno que respeta la filosofia de Sigma es PyPa. Pero bueno para este proyecto no me sirvió ;(

Anuncios

Metaclases en Python

Posted in Python por Arturo Elias Antón en 16 septiembre 2008
Tags: , , , , , , ,

En programación orientada a objetos, una metaclase es una clase cuyas instancias son clases. En otras palabras, como los objetos son instancias de una clase, las clases con instancias de una metaclase. Las metaclases nos son útiles cuando tenemos que definir la clase en tiempo de ejecución.

Metaclases en Python

En Python las Metaclases son fáciles de implementar, gracias a __metaclass__. Un ejemplo de implementación del patrón “Singleton” con metaclase se puede ver en el archivo metaclass1.py:

#!/usr/bin/python
# Nombre : metaclass1.py

class Singleton(type):
    def __init__(cls, name, bases, dct):
        cls.__instance = None
        type.__init__(cls, name, bases, dct)

    def __call__(cls):
        if cls.__instance is None:
            cls.__instance = type.__call__(cls)
            return cls.__instance

class ClassObjetoUnico:
    __metaclass__ = Singleton

a = ClassObjetoUnico()
b = ClassObjetoUnico()

print a
print b

La salida de este script es es:

>>>
<__main__.ClassObjetoUnico object at 0x00C93FB0>
None

Este patrón es el que nos garantiza que solo allá una instancia de un tipo de objeto. En este ejemplo observamos que la metaclase Singleton hereda de la metaclase type, que se sobrescribe __call__ y __init__ en Singleton y que por último se le asigna a la __metaclass__ de la clase que quiero hacer única.

  • Todas las metaclass heredan de type.
  • El método __init__, se ejecuta cuando se instancia la metaclase.
  • El método __call__, se ejecuta cada vez que se intenta instanciar un objeto por medio de la clase.
  • Por último se le asigna el atributó especial __metaclass__ la metaclase Singleton, para crear la clase por medio de dicha metaclase.

Otro ejemplo de metaclase puede ser metaclase2.y:

#!/usr/bin/python
# Nombre : metaclass2.py

class AutoNot(type):
    def __init__(cls, name, bases, dct):
       type.__init__(cls, name, bases, dct)
       methods = [x for x in dct
                  if x[0:5] == "bool_"]
       def fx(x): setattr(cls, 'not_%s' % x,
                          lambda self: not dct[x](self))
       map(fx,methods)

class A(object):
    __metaclass__= AutoNot

    def __init__(self):
        self.id=1234

    def bool_false(self):
        return False

    def bool_true(self):
        return True

a = A()

print "a.bool_true()  =",a.bool_true()
print "a.bool_false() = ",a.bool_false()
print "a.not_bool_true()  =",a.not_bool_true()
print "a.not_bool_false() = ",a.not_bool_false()

El patrón Singleton se podría haber implementado sin la necesidad de Metaclases de la siguiente manera:

#!/usr/bin/python
# Nombre : singleton.py
class Singleton(object):
    _instance=None
    def __new__(cls):
        if not cls._instance:
            cls._instance=object.__new__(cls)
            return cls._instance
    def __init__(self):
        pass

a=Singleton()
b=Singleton()

print a
print b

En el ejemplo anterior vimos, como que se sobrescribe __new__, este método se ejecuta antes que __init__ y es el verdadero creador de la instancia de clase que luego será pasado a al método __init__. Si este método no devuelve la instancia nunca se ejecutara __init__ ya que el objeto nunca existirá.

Juegos en Python (con pygame)

Hace unos años, compre un producto llamado “DIV Studio Game” y la verdad es que mi experiencia fue muy mala. Nunca terminé de familiarizar con su IDE, ni siquiera con sus librerías, la verdad no me parecían intuitivas, ni fáciles. Ese fue mi único contacto con la programación de videos juegos.
Luego después de todos estos años encontré pygame y quedé atónito con lo poco que se podía empezar a programar un juego.

¿Qué es pygame?

Pygame es un conjunto de Módulos de Python para la programación de videos juegos en 2 dimensiones. Funciona con la interfase SDL, que es una biblioteca multiplataforma para el manejo de la programación gráfica.
Para empezar a usarlo tendremos que bajarlo de su pagina oficial http://www.pygame.org/.

Programando con pygame

Pygame se encargara de gestionar toda la parte multimedia de nuestro juego como pueden ser el manejo de imágenes, el sistema de sonido, operaciones relacionadas con el gestor de ventanas, eventos de nuestro juego, temporizadores, colisiones, etc.
Casi todos los videos juego responden a una misma lógica básica. Esta lógica seria:

  • Iniciar pygame.
  • Iniciamos nuestra ventana.
  • Comenzamos un bucle infinito.
  • Choquemos los eventos y actuamos según corresponda.

Un ejemplo diminuto de esta lógica pygame1.py

#!/usr/bin/python
# Nombre : pygame1.py
import pygame
import sys

pygame.init;
pygame.display.set_mode((320,240))

while True:
    for e  in pygame.event.get():
        if e.type == pygame.QUIT: #si llega el evento QUIT
            sys.exit(0)          #Sale del sistema

El evento pygame. QUIT es cuando un usuario intenta cerrar la ventana. Si no hacemos esto la ventana no responderá a este vento y nunca se cerrara. Como pasa en el ejemplo pygame2.py que solo sale al tocar la tecla “s” no saldrá de la ventana.

#!/usr/bin/python
# Nombre : pygame2.py
import pygame
import sys

pygame.init; #inicializa pygame
pygame.display.set_mode((320,240)) #inicializamos video

while True: #bucle infinito
    for e  in pygame.event.get():
        if e.type == pygame.KEYUP: #si solto alguna tecla
            if e.key == pygame.K_s: sys.exit(0)
            # cuando suelte la tecla "s"

En este ejemplo también se puede observar otro evento llamado KEYUP que ocurre cuando un usuario suelta una tecla y también se observa cuando como se obtiene la tecla en cuestión mediante “e.key”.

También podremos ponerle un fondo a nuestro ejemplo. De la forma siguiente:

#!/usr/bin/python
# Nombre : pygame3.py

import pygame
import sys

pygame.init; #inicializa pygame

screen = pygame.display.set_mode((320,240),pygame.FULLSCREEN)

fondo = pygame.image.load("img/2145_1101395673.png")

while True: #bucle infinito
    #recorremos los eventos recividos
    for e  in pygame.event.get():
        if e.type == pygame.KEYUP: #si solto alguna tecla
            if e.key == pygame.K_s: sys.exit(0)
            # cuando suelte la tecla "s"
    screen.blit(fondo,(0,0))
    pygame.display.flip()

El fondo lo cargamos con pygame.image.load y luego lo dibujamos en memoria mediante “blit”. Para imprimirlo en pantalla luego con “pygame.display.flip()”.

Nosotros le pondremos a nuestro juego una pelota que podamos manejar mediante las flechas del teclado. Esto lo podemos ver en el ejemplo pygame4.py

#!/usr/bin/python
# Nombre : pygame4.py
import pygame
import sys

from pygame.locals import *

class Pelotas (pygame.sprite.Sprite):
    def __init__(self,img):
        self.image = pygame.image.load(img)
        self.rect = self.image.get_rect()
        self.rect.move_ip(0,0)

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[K_RIGHT] : self.rect.x += 2
        if keys[K_LEFT]  : self.rect.x -= 2
        if keys[K_UP]  : self.rect.y -= 2
        if keys[K_DOWN]: self.rect.y += 2

pygame.init;
screen = pygame.display.set_mode((320,240))

pelota = Pelotas("img/ball.png")

while True: #bucle infinito
    for e  in pygame.event.get(): #recorremos los eventos recividos
        if e.type == pygame.KEYUP: #si solto alguna tecla
            if e.key == pygame.K_s: sys.exit(0) # cuando suelte la tecla "s"
    pelota.update()
    screen.fill((0,0,0)) #restablecemos el color del fondo
    screen.blit(pelota.image,pelota.rect)
    pygame.display.flip()

Comentario del “pygame4.py”: Lo primero que hacemos es definir una clase Pelotas que hereda de pygame.sprite.Sprite. ¿Qué son los sprite? Un sprite es simplemente una figura o imagen de dimensiones no muy grandes, que puede desplazarse por la pantalla. Y en nuestro caso será una pelota que la podremos mover mediante las flechas, para esto redefinimos el metodo “update” y dentro del mismo, obtenemos las teclas pulsadas por medio de la función pygame.key.get_pressed(), que nos devuelve una lista con el estado de todas las teclas. Luego lo chequeamos según la posición de cada tecla en la lista que nos devolvió dicha función. También vemos en esta clase que redefinimos el constructor para asignarle la propiedad “image” y la propiedad “rec”.

  • Image: es la imagen propiamente dicha que usa el sprite.
  • Rec: es el rectángulo de dicha imagen.

Luego en el while infinito agregamos update para que podamos tomar el control de nuestra pelota y fill para restablecer el fondo de la pantalla. El método fill recibe por parámetro un color en formato RGB por parámetro. Prueben sacarlo y ver que pasa.

Un Juego simple y completo en pygame.

En esta sección veremos como detectar cuando un sprite se choca o colisiona con otro sprite. Para esto crearemos un juego, donde halla muchas pelotas flotando por todos lados y nuestra pelota parezca en el inicio de juego en la esquina superior derecha y tengamos que trasportarla hasta la esquina inferior izquierda sin chocar con ninguna otra pelota.

Acá esta el código. pygame5.py

#!/usr/bin/python
# Nombre : pygame5.py
import pygame
import sys

from pygame.locals import *

ancho,largo = 500,400

clock = pygame.time.Clock
class Pelotas (pygame.sprite.Sprite):
    def __init__(self,img):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(img)
        self.rect = self.image.get_rect()
        self.rect.move_ip(0,0)
        self.rectAnt = self.rect
        self.t=0

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[K_RIGHT] and self.rect.x < ancho-30:
            self.rect.x += 2
        if keys[K_LEFT] and self.rect.x > 10 :
            self.rect.x -= 2
        if keys[K_UP] and self.rect.y > 10:
            self.rect.y -= 2
        if keys[K_DOWN] and self.rect.y < largo-30:
            self.rect.y += 2

        screen.blit(self.image,self.rect)
        c = len(pygame.sprite.spritecollide(self,g,False,None))
        if c >= 2:
            print "Perdiste: Uff chocaste",c
            sys.exit(0)

        if self.rect.x == ancho - 30 and self.rect.y == largo-30:
            print "Wiiii GANASTE"
            sys.exit(0)
        else:
            self.t+=1

        self.rectAnt = self.rect

class Elementos (pygame.sprite.Sprite):
    def __init__(self,img,x,y,p):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(img)
        self.rect = self.image.get_rect()
        self.rect.move_ip(x,y)
        self.direccion = p
    def update(self):
        keys = pygame.key.get_pressed()
        self.rect.x += self.direccion[0]
        self.rect.y += self.direccion[1]

        if self.rect.x > ancho-10: self.direccion[0] = -1
        if self.rect.x < 30      : self.direccion[0] = 1
        if self.rect.y < 30      : self.direccion[1] = 1
        if self.rect.y > largo-10: self.direccion[1] = -1
        c=len(pygame.sprite.spritecollide(self,g,False,None))
        if c >= 2:
            self.direccion[0] = self.direccion[0]*(-1)
            self.direccion[1] = self.direccion[1]*(-1)
        screen.blit(self.image,self.rect)

pygame.init;

screen = pygame.display.set_mode((ancho,largo))

pelota = Pelotas("ball.jpg")
elemento1 = Elementos("ball.jpg",0,150,[1,1])
elemento2 = Elementos("ball.jpg",150,0,[1,2])
elemento3 = Elementos("ball.jpg",300,120,[3,1])
elemento4 = Elementos("ball.jpg",400,65,[1,5])
elemento5 = Elementos("ball.jpg",470,65,[1,-95])
elemento6 = Elementos("ball.jpg",450,10,[-1,3])
elemento7 = Elementos("ball.jpg",400,65,[25,5])

g = pygame.sprite.Group()
ge=pygame.sprite.Group()
g.add([pelota,elemento1,elemento2,elemento3,elemento4,elemento5,elemento6,elemento7])
ge.add([elemento1,elemento2,elemento3,elemento4,elemento5,elemento6,elemento7])

while True:
    for e  in pygame.event.get():
        if e.type == pygame.KEYUP:
            if e.key == pygame.K_s: sys.exit(0)
    screen.fill((0,0,0))
    g.update()
    pygame.time.delay(10)
    pygame.display.flip()

En este código, ya más complejo, se puede ver un juego simple pero completo. Lo primero que observamos es que se agregan, los grupos. Estos “grupos” dan la posibilidad de enviarles mensajes de una sola vez a nuestros sprite y también observamos que se crean mediante la clase “pygame.sprite.Group ()” y le podemos agregar sprite, mediante el método add.
En el while infinito podemos ver como por medio de g.update(). Le enviamos a todos el método update(). Luego hacemos un delay por medio de la función “pygame.time.delay(10)” para que el juego no valla tan rápido. En las clases podremos ver como controlamos las colisiones con otros sprite por medio de “pygame.sprite.spritecollide”.

Agregar un Nodo a un XML

Para agregar un nodo a un XML es simple solo tendremos que seguir en siguiente algoritmo.

  • Crear un nodo elemento
  • Crear un nodo texto (si lo requiere)
  • Agregarle el nodo texto al nodo elemento creado
  • Agregar el nodo elemento creado a algún nodo del documento xml

Observemos en el siguiente ejemplo como lo hace

#!/usr/bin/python
# Nombre : xml3.py
import xml.dom.minidom
xmldoc = xml.dom.minidom.parse("./xml1.xml")

for n in  xmldoc.childNodes :
    print n.tagName
    for contacto in n.childNodes:
        if contacto.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
            nodo = xmldoc.createElement("ElemntoAgrgado")
            nodo.appendChild(xmldoc.createTextNode("Agregue un textnode"))
            contacto.appendChild(nodo)
        for registro in contacto.childNodes:
            if registro.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
                print registro.nodeName ,"-" , registro.firstChild.data
                registro.firstChild.data =  registro.firstChild.data

fp = open("./xml2.xml", 'w')

xmldoc.writexml(fp)
fp.close()

Crea el nodo elemento por medio del método “createElement” y luego le agrega el nodo texto, creado por medio de “createTextNode”, con el método “appendChild”. Y por último también con el metodo appendChild lo agrega al nodo contacto del documento.
Para guardar los cambios crea un archivo y lo guarda por medio del método “writexml”

Gracias a la aclaracion de Alejandro J. Cura decidi rearmar el ejemplo anterior con la libreria “elementtree”.

#!/usr/bin/python
# Nombre : xml4.py
from elementtree.ElementTree import  SubElement
from elementtree import ElementTree

xmlFp = open("xml1.xml", "r")
xmldoc = ElementTree.parse(xmlFp)
agenda = xmldoc.getroot()

print dir(agenda)
print agenda.text
for c in agenda.getiterator("contacto"):
    nodo = SubElement(c, "ElemntoAgrgado")
    nodo.text = "Agregue un textnode"
    for registro in c.getiterator():
        if registro != c:print registro.tag ,"-", registro.text

xmldoc.write(file="./xml2.xml")

Gracias Alejandro.
y todas sus ideas son bien recibidas!!!!!!!!!!!

XML en Python

XML (Extensible Markup Language): Es un meta-lenguaje que permite definir lenguajes de marcado. En la práctica es un estándar que permite a diferentes aplicaciones interactuar con facilidad.  XML fue creado con la supervisión del World Wide Web Consortium (W3C), organismo que maneja los estándares de la Web, basándose en las especificaciones del lenguaje SGML. Su desarrollo se comenzó en 1996 y la primera versión salió a la luz el 10 de febrero de 1998.

Estructura de XML

El XML consta de con 4 especificaciones:

  • DTD (Document Type Definition): Definición del tipo de documento. Es en general, un archivo que encierra una definición formal de un tipo de documento y, a la vez, especifica la estructura lógica de cada documento. El DTD del XML es opcional.
  • XSL (eXtensible Stylesheet Language): Es el lenguaje de estilo del XML. Es el que le cambia el aspecto al documento.
  • XLL (eXtensible Linking Language): Define el modo de enlace entre diferentes enlaces.
  • XUA (XML User Agent): Estandarización de navegadores XML. Todavía está en proceso de creación de borradores de trabajo.

Con el XML que trabajaremos en esta entrada es:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<agenda>
    <contacto>
        <nombre>Ariadna</nombre>
        <apellido>Bouzo</apellido>
        <numero tipo="tel">43050412</numero>
        <direccion>okla 4501</direccion>
    </contacto>
    <contacto>
        <nombre>Arturo Elias</nombre>
        <apellido>Anton</apellido>
        <numero tipo="cel">1563442356</numero>
        <direccion>pepiri 1524</direccion>
    </contacto>
    <contacto>
        <nombre>Pedro</nombre>
        <apellido>Colono</apellido>
        <numero tipo="cel">1565214578</numero>
        <direccion>av Colon 1245</direccion>
    </contacto>
    <contacto>
        <nombre>Eduardo</nombre>
        <apellido>Ramos</apellido>
        <numero tipo="tel">45213652</numero>
        <direccion>Luna 4512</direccion>
    </contacto>
    <contacto>
        <nombre>Rocio</nombre>
        <apellido>Gomez</apellido>
        <numero tipo="cel">1551253652</numero>
        <direccion>Cordoba 1254</direccion>
    </contacto>
</agenda>

Observe que si bien uno en XML puede crear sus propias tag o marcas, siempre lo tienen que escribir igual ya que XML es sensible a minúsculas y mayúsculas. Otra cosa que XML nos exige, es que cada marca que abrimos la cerremos. En otras palabras XML nos exige que el documento que armemos sea “bien formado”.
Python para el manejo de estos documentos nos facilita de un paquete “xml” y dentro del mismo estarán los parse de DOM y SAX.

DOM y SAX

DOM y SAX, son las dos herramientas  mas extendidas que sirven para analizar XML y definir la estructura de un documento, aunque existen otras. Una de las diferencias más grandes entre ellas es que las primeras verifican que el documento, además de estar bien formado de acuerdo a las reglas de XML, responda a una estructura definida en una Definición del Tipo de Documento (DTD).

Leer un XML

Para leer un XML lo primero que haremos es importar xml.dom.minidom luego obtendremos un objeto que represente nuestro documento “xml1.xml” mediante la palabra xml.dom.minidom.parse de la siguiente manera:

#!/usr/bin/python
# Nombre : xml1.py
import xml.dom.minidom
xmldoc = xml.dom.minidom.parse("./xml1.xml")

for n in xmldoc.getElementsByTagName("contacto"):
    print n.toxml()
    print n.firstChild.data

for n in xmldoc.getElementsByTagName("nombre"):
    print n.toxml()
    print n.firstChild.data

for n in xmldoc.getElementsByTagName("direccion"):
    print n.toxml()
    print n.firstChild.data

for n in xmldoc.getElementsByTagName("numero"):
    print n.toxml()
    print n.firstChild.data
    print n.getAttribute("tipo")
    print n.attributes.keys()
    print n.attributes["tipo"].value

Para leer un XML lo primero que haremos es importar xml.dom.minidom luego obtendremos un objeto que represente nuestro documento “xml1.xml” mediante la palabra xml.dom.minidom.parse de la siguiente manera
También podemos observar en este código como obtenemos los distintos nodos por medio de getElementByTagName. Este  metodo tan familiar para los programadores JavaScript  es de gran utilidad ya que nos retorna una lista con todos los nodos hijos desde el nodo donde se invoque y que coincidan con el nombre del tag. También observamos algunos métodos y propiedades como son:

  • toxml: este método nos devuelve el código XML.
  • firstChild: esta propiedad es el enlace al primer nodo hijo
  • getAttribute: obtiene el valor de una propiedad determinada del tag
  • attributes: es un diccionario de propiedades del tag

También se podría haber recorrido de esta manera

#!/usr/bin/python
# Nombre : xml2.py
import xml.dom.minidom
xmldoc = xml.dom.minidom.parse("./xml1.xml")

for n in  xmldoc.childNodes :
    print n.tagName
    for contacto in n.childNodes:
        for registro in contacto.childNodes:
            if registro.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
                print registro.nodeName ,"-" , registro.firstChild.data

Después de instanciar nuestro objeto xml lo que hacemos es recorrer todos los nodos hijos de él, y luego recorremos todos sus hijos  gracias a childNodes que no es mas que una lista con todos los nodos hijos de  un nodo padre. Luego tendremos que tener cuidado  la hora de imprimir ya que no todos son nodos de tipo element también existen los nodos de tipo text. Los nodos de tipo text son siempre los nodos hojas del árbol DOM y tienen el atributo data para recuperar su valor.

Paquetes en python

Posted in Python por Arturo Elias Antón en 8 septiembre 2008
Tags: , ,

Un paquete es una manera de organizar un conjunto de módulos como una unidad. Los paquetes pueden a su vez contener otros paquetes.
En realidad los paquetes no son más que directorios con un archivo llamado “__init__.py” que importa todos los módulos y paquetes que contiene el paquete.

Haremos de ejemplo el paquete “nuestro_paquete”:

  • Creamos un directorio llamado “nuestro_paquete”
  • Entramos a directorio llamado “nuestro_paquete”
  • Creamos el modulo “cuadratica.py”:
# Nombre : cuadratica.py
import math

def determinante(a,b,c):
    return (b*b)-(4*a*c)

def calculaRaiz(a,b,c):
    det = determinante(a,b,c)
    if det < 0:
        print "tiene raices imaginarias"
    else:
        print "La rais 1 es " + str((b + math.sqrt(det))/(2*a))
        print "La rais 2 es " + str((b - math.sqrt(det))/(2*a))
  • Creamos otro modulo llamado calculoMedio.py :
# Nombre : calculoPuntoMedio.py
def calcMedMedio(a,b):
    return (b-a)/2.0
  • Dentro del directorio “nuestro_paquete” creamos el archivo “__init__.py”como el siguiente:
# nuestroPaquete
from cuadratica import calculaRaiz
from calculoPuntoMedio  import calcMedMedio
  • Salimos del directorio “nuestro_paquete”
  • Escribimos el archivo “usoPaquete.py”
#!/usr/bin/python
# Nombre : usoPaquete.py
import nuestro_paquete
nuestro_paquete.calculaRaiz(3,9,6)
print "El punto medio de 3 y 9 es " , nuestro_paquete.calcMedMedio(3,9)

La estructura de directorios nos tendría que quedar así:

C:\py\nuestro_paquete>dir
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es: E8B7-DAAC

 Directorio de C:\py\nuestro_paquete

03/09/2008  17:13    <DIR>          .
03/09/2008  17:13    <DIR>          ..
03/09/2008  17:08                99 calculoPuntoMedio.py
03/09/2008  16:58               375 cuadratica.py
03/09/2008  17:08                81 __init__.py
               3 archivos            555 bytes
               2 dirs  136.206.897.152 bytes libres

C:\py\nuestro_paquete>cd ..

C:\py>dir
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es: E8B7-DAAC

 Directorio de C:\py

03/09/2008  17:02    <DIR>          .
03/09/2008  17:02    <DIR>          ..
03/09/2008  17:13    <DIR>          nuestro_paquete
03/09/2008  17:05               107 usoPaquete.py
               1 archivos            107 bytes
               3 dirs  136.206.958.592 bytes libres

C:\py>

La localización de los paquetes debe especificarse o bien a través de la variable de entorno PYTHONPATH o en código del script mediante sys.path

Modulos en python

Posted in Python por Arturo Elias Antón en 6 septiembre 2008
Tags: , , , , ,

Un módulo es una colección de funciones procedimientos y clases en un fichero que acaba en “.py”. El nombre del fichero determina el nombre del módulo. Para poder usar los contenidos del modulo que creemos simplemente lo tendremos que importarlo con la palabra reservada “import”.

Por ejemplo armaremos un archivo llamado cuadratica.py

# Nombre : cuadratica.py
import math

def determinante(a,b,c):
    return (b*b)-(4*a*c)

def calculaRaiz(a,b,c):
    det = determinante(a,b,c)
    if det < 0:
        print "tiene raices imaginarias"
    else:
        print "La rais 1 es " + str((b + math.sqrt(det))/(2*a))
        print "La rais 2 es " + str((b - math.sqrt(det))/(2*a))

Y luego lo usaremos en el archivo usa_modulo.py

#!/usr/bin/python
# Nombre : usa_modulo.py
import cuadratica
cuadratica.calculaRaiz (3,9,6)

Otra forma de uso o mejor dicho de invocación del modulo es invocar solo la función que necesitamos de dicho modulo. Esto nos da la ventaja de que no tendremos que poner el nombre del modulo antes de la función que queramos invocar.

#!/usr/bin/python
# Nombre : usa_modulo2.py
from cuadratica import calculaRaiz
calculaRaiz(3,9,6)

Navegando con Python (urllib2)

Posted in Python por Arturo Elias Antón en 4 septiembre 2008
Tags: , , , , , , , ,

Modulo para lectura de URLs

Python nos facilita el módulo urllib2 para la interacción con URLs, tambien existe urllib. Pero aunque su uso  es muy parecido, es menos completa que urllib2.
El modulo urllib2 puede leer datos de una URL usando varios protocolos como HTTP, HTTPS, FTP, o Gopher.

Obtener una Web

Para obtener un streem con el contenido de una página Web solicitaremos a la función urlopen del cualquiera de los módulos ya mencionados. Luego este stream podrá ser leído por medio de los métodos read, readline. Y también podrá ser cerrado por medio del método close.

El ejemplo más simple es el que veremos aquí:

#!/usr/bin/python
# Nombre de Fichero: urllib2_1.py

import urllib2
response = urllib2.urlopen('http://www.yahoo.com.ar/')
html = response.read()

HTTP se basa en pedidos y respuestas. El cliente hace una solicitud al servidor y el servidor responde. El modulo urllib2 nos permite crear nuestra petición que representa la petición HTTP que están haciendo. En su forma más simple de crear una Solicitud de objeto que especifica la URL que desea buscar. Luego llama a urlopen con esta solicitud objeto como parámetro y urlopen nos devuelve una respuesta objeto de la URL solicitada:

El ejemplo se puede ver aca:

#!/usr/bin/python
# Nombre de Fichero: urllib2.py

import urllib2
import sys

web=raw_input("Web es http://")
userAgent = 'NuestroNavegador'
headers = { 'User-Agent' : userAgent }
req = urllib2.Request("http://"+web , None, headers)
response = urllib2.urlopen(req)
print response.read()
response.close()

También podremos necesitar que nuestro cliente Web se valida ante un proxy, esto es muy común cuando nuestro script corre dentro de una empresa.

La modificación de urllib2.py se valida ante un proxy seria proxy.py

#!/usr/bin/python
# Nombre de Fichero: proxy.py

import urllib2
import getpass
import sys

proxyuser=raw_input("Ingrese usuario:")
proxypass= getpass.getpass("Enter proxy password:")
httpproxy=raw_input("Ingrese la direccion del proxy:")
proxy=urllib2.ProxyHandler({"http":'http://'+proxyuser+':'+proxypass+'@'+httpproxy})
authinfo=urllib2.HTTPBasicAuthHandler()
opener=urllib2.build_opener(proxy, authinfo,urllib2.HTTPHandler)
urllib2.install_opener(opener)

web=raw_input("Web es http://")
userAgent = 'NuestroNavegador'
headers = { 'User-Agent' : userAgent }
req = urllib2.Request("http://"+web , None, headers)
response = urllib2.urlopen(req)
print response.read()
response.close()

HTTPError y URLError

Dos errores que tenemos que tener en cuenta cuando manejamos urllib2 son:

  • URLError: son errores que lanza la librería.
  • HTTPError: es el error que nos envía el servidor como el conocido 404 cuando no encuentra la pagina

También nos podemos encontrar con errores lanzados por módulos que utiliza urllib2 como httplib o el propio módulo e socket

Socket en Python

Posted in Python por Arturo Elias Antón en 3 septiembre 2008
Tags: , , , ,

¿Que es un socket?
Según Beej un socket es:

“Una forma de comunicarse con otros programas usando descriptores de fichero estándar de Unix..”[Guía Beej de Programación en Redes por Brian “Beej” Hall Link]

La programación de sockets se diferencia de la programación de aplicación tradicional, en que trabajamos con procesos que funcionan concurrentemente. Los socket enlazan procesos asincrónicos con un solo canal bidireccional.

En esta entrada solamente hablaremos de los sockets de dominio de internet, los de la familia AF_INET, existen otras familias de socket como las AF_UNIX, AF_FILE, AF_IPX, AF_AX25, etc., pero esos no serán tratados en esta entrada.

Los tipos de socket son

  • SOCK_STREAM: Este protocolo nos da una comunicación fiable de dos direcciones en un flujo de datos(TCP)
  • SOCK_DGRAM: Este protocolo nos da una conexión no fiable. (UDP)
  • SOCK_RAW: este protocolo es para acceder a los campos e interfaces internos de la red.
  • SOCK_RDM: Este protocolo garantiza el la llegada de paquetes pero no garantiza el orden de llegada
  • SOCK_SEQPACKET: datagramas fiables y secundarios, de longitud fija, basado en la conexión.
  • SOCK_PACKET Coloca el socket en modo promiscuo en la que recibe todos los paquetes de la red.

Para el parámetro type nosotros solo trataremos el del tipo SOCK_STREAM.

Métodos del Socket

Los métodos más importantes del socket son:

  • socket.socket: Crea un canal bidireccional con el que generalmente se establece una conexión de red
  • socket.bind: Define un puerto y un nombre para un socket.
  • socket.listen: Convierte el socket en un socket en escucha
  • socket.accept: Espera que llegue una conexión. Al llegar la descripción devuelve un socket nuevo para dicha conexión especifica
  • socket.connect: Conecta un socket con otro que lo este esperando en un puerto y dirección especifica
  • socket.send: Es por el método que enviaremos los mensajes
  • socket.recv: Es por el método que recibiremos los mensajes
  • socket.close: Cierra el socket.

Pasos para la creación de un programa que utiliza Socket

Los sockets, primero que nada necesitan un proceso que sea  servidor. Un servidor genérico realiza las siguientes tareas:

  • Crea un socket mediante socket.socket(famili,tipo)
  • Asocia el puerto por medio del método bind()
  • Pasa al socket a modo esperas mediante el método listen()
  • Espera una conexión con el método accept()
  • Lee o escribe los mensajes por medio del método recv() o send()
  • Al termino de la conexión se realiza con el método close()

Un ejemplo de un servidor simple es:

#!/usr/bin/python
# Nombre de Fichero : servidor.py

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("", 8000))
server.listen(10)
while 1:
    add, port = server.accept()
    add.send("Usted se conecte al servidor")

Observemos que el parámetro de bind es una tupla.
El servidor que simplemente nos deja conectarnos y nos envía la cadena “Usted se a conectado al servidor” por medio del método send.

Los sockets tienen también otros procesos denominados cliente, lo que realizan estos son:

  • Crea un socket
  • Conectarse a una dirección y puerto de destino por medio del método connect()
  • Lee o escribe los mensajes por medio del método recv() o send()
  • Al termino de la conexión se realiza con el método close()

Un ejemplo de un cliente simple es:

#!/usr/bin/python
# Nombre de Fichero : servidor.py

#!/usr/bin/python
# Nombre de Fichero: cliente.py

import socket

cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cliente.connect(("127.0.0.1", 8000))
print cliente.recv(255)
cliente.close()

Observemos  que el parámetro de connect es una tupla

Enviando y recibiendo datos

Los métodos de un socket para enviar y recibir mensajes son iguales para el servidor que para el cliente.  Estos métodos ya vistos en los dos ejemplos anteriores son.

•    recv: Recibe la cantidad del largo del buffer a recibir
•    send: Envía por parámetro el dato a enviar

Observemos en este servidor que imprime todos los datos que llega

#!/usr/bin/python
# Nombre de Fichero : servidor.py

#!/usr/bin/python
# Nombre de Fichero: servidoMuestraTodo.py
import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("", 8002))
server.listen(10)
while 1:
    add, port = server.accept()
    print add.recv(255)
    add.close()

La salida de este programa, si nos conectamos a el por medio de un browser como puede ser firefox, será parecida a esta

>>>
GET / HTTP/1.1
Host: 127.0.0.1:8002
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: es-es,es;q=0.8,en-us;q=

Bien analizando esto podremos ver que el navegador no solicita con el comando GET la pagina que tenemos en el raíz y nos envía mucha mas información como el sistema operativo en el que esta trabajando.

Sincronización de hilos en python

Para poder sincronizar el acceso de nuestros hilos, en modulo de threading nos facilita estos métodos de sincronización : mutex, locks re-entrantes, semáforos, condiciones y eventos.

Mutex o locks o Candados

Realmente los mutex son la herramienta más fácil que hay de sintonización. Un mutex se usa en programación concurrente para que un solo procesos o hilo en nuestro caso pueda tomar un recurso compartido por otros. La parte de código que toma dicho recurso se llama sección crítica. El mutex solo puede tomar dos estados que son tomados y liberado. Miremos un ejemplo para aclarar las ideas.

En el archivo mutex.py y compare su salida con el de hilo.py de la entrada anterior

#!/usr/bin/python
# Nombre de Fichero : mutex.py

import threading
from time import sleep
mutex = threading.Lock()
class Hilo(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        mutex.acquire()
        sleep(3-self.id)
        print "Yo soy %s la variable d tiene el valor %s"%(self.id,d)
        mutex.release()

d=1;
hilos = [Hilo(1),
Hilo(2),
Hilo(3)]

for h in hilos:
    h.start()

Bueno veremos otro ejemplito llamado mutex1.py

#!/usr/bin/python
# Nombre de Fichero : mutex.py

import threading
from time import sleep
mutex = threading.Lock()

n=0
class Hilo(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        mutex.acquire()
        sleep(3-self.id)
        d.append(self.id)
        mutex.release()

d=[];
hilos = [Hilo(1),
Hilo(2),
Hilo(3)]

for h in hilos:
    h.start()

mutex.acquire()
print d
mutex.release()

comparemos la salida con mutex.acquire() y sin él. Recorrar que por cada mutex.acquire() que sacamos tenderemos que sacar tambien el mutex.release()
sino se nos quedara bloqueado el hilo de ejecución. Igual mente me parece que esta buene que vean como se bloquea al sacar el release.

locks re-entrantes – Rlook
La clase RLock es similar a Lock, pero puede ser adquirido por el mismo thread varias veces, y no quedará liberado hasta que el thread lo libere tantas veces como llamó a acquire.

Los semáforos

Los semáforos son parecidos a los mutex pero en vez de tomar el valor 1 y 0, toman n valores que nos indicara la cantidad de hilos, que puede tomar el recurso concurrentemente. Para esto python nos facilita la clase Semaphore y BoundedSemaphore. La diferencia de Semaphore y BoundedSemaphore es que, cuando se libera el recurso más veces que el n inicial del semáforo en Semaphore cambia dicha cota, mientras que en BoundedSemaphore lo considera un error de ValueError

Miremos este ejemplo llamado semaphore.py

#!/usr/bin/python
# Nombre de Fichero : semaphore.py

import threading
from time import sleep
semaforo = threading.Semaphore(2)

n=0
class Hilo(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        semaforo.acquire()
        sleep(3-self.id)
        d.append(self.id)
        semaforo.release()

d=[];
hilos = [Hilo(1),
Hilo(2),
Hilo(3)]

for h in hilos:
    h.start()

sleep(4)
semaforo.acquire()
print d
semaforo.release()

fijese que si agrega justo antes del sleep(4) 3 release como estos

semaforo.release()
semaforo.release()
semaforo.release()

La salida cambia de orden ya que entra mas de uno hilo concurrente.
En cambio si después de agregar estas tres lineas, cambiamos la linea
semaforo = threading.Semaphore(2) por semaforo = threading.BoundedSemaphore(2)
dara error de tipo ValueError.

Las condiciones

Las condiciones son de utilidad para hacer que los threads sólo puedan entrar en la sección crítica de darse una cierta condición o evento.La clase condition tiene métodos wait, notify y notifyAll.

El método wait debe llamarse después de haber adquirido el objeto condiction con acquire. Este método libera el candado y bloquea al hilo hasta que una llamada a notify o notifyAll en otro hilo le indican que se ha cumplido la condición. El hilo que informa a los demás de que se ha producido la condición, también debe llamar a acquire antes de llamar a notify o notifyAll.

Espero que el ejemplo del archivo condition.py sea ilustrativo.

#!/usr/bin/python
# Nombre de Fichero : condition.py
import threading

cond = threading.Condition()

class Cliente (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        while True:
            cond.acquire()
            cond.wait()
            mesa.pop()
            cond.notify()
            cond.release()

class Cosinero(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        while True:
            cond.acquire()
            if len(mesa) != 0: cond.wait()
            mesa.append("Torta de frutillas")
            cond.notify()
            cond.release()

print "El bar"

mesa = []
cliente = Cliente()
cosinero = Cosinero()

cliente.start()
cosinero.start()

while True:
    print mesa

acquire no bloqueante

Para que acquire no bloque el hilo le tenemos que pasar (False) como parámetro. Dicha invocación nos dará el resultado de si obtuvo el hilo o no. Modificaremos el ejemplo del mutex para que se vea lo que pasa.

#!/usr/bin/python
# Nombre de Fichero : mutex2.py

import threading
from time import sleep
mutex = threading.Lock()
class Hilo(threading.Thread):
    def __init__(self, id):
        threading.Thread.__init__(self)
        self.id = id

    def run(self):
        b = mutex.acquire(False)
        print b
        sleep(3-self.id)
        print "Yo soy %s la variable d tiene el valor %s"%(self.id,d)
        if b :mutex.release()

d=1;
hilos = [Hilo(1),
Hilo(2),
Hilo(3)]

for h in hilos:
    h.start()

Los eventos

La clase Event es un wrapper por encima de Condition y sirven principalmente para coordinar threads mediante señales que indican los eventos que han ocurrido. Los no tienen los métodos acquire y release.
El hilo que debe esperar el evento se pondra en espera por medio de la llama al método wait y se bloquea, le podriamos pasar como parámetro un número en coma flotante indicando el número máximo de segundos a esperar. Otro hilo, cuando ocurre el evento, envía la señal a los hilos bloqueados a la espera de dicho evento utilizando el método set. Los hilos que estaban esperando se desbloquean una vez recibida la señal. La bandera que indica si se ha producido el evento se puede volver a setar a falso usando clear. Los eventos son similares a las condiciones.

Un ejemplo lo vemos en eventos.py que es una modificación de condition.py

#!/usr/bin/python
# Nombre de Fichero :  eventos.py
import threading

evento = threading.Event()

class Cliente (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        while True:
            self.evento.wait()
            mesa.pop()

class Cosinero(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        while True:
            if len(mesa) != 0: cond.wait()
            mesa.append("Torta de frutillas")
            evento.set()

print "El bar"

mesa = []
cliente = Cliente()
cosinero = Cosinero()

cliente.start()
cosinero.start()

while True:
    print mesa
Página siguiente »