Python viene con las baterías incluídas

CaFeConf 2005

Facundo Batista

facundo@taniquetil.com.ar

www.taniquetil.com.ar

Arte gráfico: Diana Batista

Indice

Qué es Python

La Biblioteca Standard

Ejemplo: Un buscador

Construímos el índice

Servimos las búsquedas

Demo!

Qué es Python

Algunas características

Propiedades del lenguaje

Productividad

Algunas características

Gratis Y Libre

Y Open Source, todo por el mismo precio: cero

Maduro (+14 años)

Diseño elegante y robusto

Fácil de aprender

Se lee como pseudo-código

Extremadamente portable

Unix, Windows, Mac, BeOS, Win/CE

DOS, OS/2, Amiga, VMS, Cray

...

Propiedades del lenguaje

Compila a bytecode interpretado

La compilación es implícita y automática

Tipado dinámico, polimorfismo

Sobrecarga de operadores

Multi-paradigma

Todo son objetos

Pero puede usarse de manera procedural

Módulos, clases, funciones

Manejo de excepciones

Tipos de datos de alto nivel

Enteros sin límites, strings, flotantes, complejos

Listas, diccionarios, conjuntos

Productividad

Tiempo reducido de desarrollo

el código es 2 a 10 veces más corto que C, C++ o Java

Menos entrenamiento

El lenguaje es muy fácil de aprender

Mejor mantenimiento de los programas

El código es extremadamente legible

Jolt Productivity Award

Por segunda vez (antes en el 2000)

Categoría: Languages and Development Tools

Enterprise-class

Frequentis TAPtools: Control de tráfico aéreo.

Industrial Light & Magic: Gestión de las granjas de renderizado.

NASA: Sistemas computarizados de diseño y fabricación.

Google: Administración de decenas de miles de servidores.

La Biblioteca Standard

Acceso al Sistema Operativo

Protocolos y datos

Servicios del lenguaje y misceláneos

Acceso al Sistema Operativo

Servicios genéricos y opcionales del sistema

Acceso a conversiones y servicios de la hora

Administración de subprocesos

Servicios de Internacionalización y Localización

Manejo de sockets, threads y comunicación entre procesos

Lee y escribe archivos con formato ZIP, bzip2, gzip, tar

Específicos por Sistema

Acceso a la información de usuarios y grupos de Unix

Llama a funciones C en objetos compartidos de Unix

Información de uso de recursos del proceso actual en Unix

Manejo del Registro de Windows y rutinas varias del runtime Microsoft VC++

Acceso a los servicios y hardware de audio en IRIX, SunOS y Windows

Funciones de la biblioteca gráfica de Silicon Graphics en IRIX

Protocolos y datos

Acceso a Protocolos y manejo de datos de Internet

Cliente y servidor de XML-RPC

Servicios de manejo asincrónico de sockets

Clientes HTTP, FTP, SMTP, GOPHER, POP3, IMAP4, NNTP

Servidores HTTP, SMTP

Herramientas de trabajo con MIME

Codecs binhex4, MIME imprimible, uuencode, XDR, csv

Manejo de cadenas y XML

Búsqueda y coincidencias usando Expresiones Regulares

Lee y escribe cadenas como si fuese archivos

Acceso a la Base de Datos de Unicode

Parsers SGML, HTML, XHTML

Manejo de XML: DOM y SAX

Servicios del lenguaje y misceláneos

Servicios del lenguaje

Interfaz para el garbage collector

Extrae información y código fuente de objetos vivos

Convierte objetos de Python a secuencia de bytes y viceversa

Provee un depurador interactivo y un perfilador del código fuente

Compilador, decompilador, análisis lexicográfico y acceso a árboles de parseo de Python

Misceláneos:

Docs: Generador de documentación y ayuda online

Testeo: Entorno para unit testing y pruebas a partir de los docs

Matemática: Funciones para números reales y complejos

Criptografía: Algoritmos MD5 y SHA, y Autenticación HMAC

Interfaz gráfica integrada: Tk/Tcl

Multimedia: Manejo de datos de audio y video y acceso a dispositivos OSS

Ejemplo: Un buscador

Objetivo

Estructura

Objetivos

Del ejemplo:

Mostrar cuán fácil es armar un sistema complejo

Pocas lineas de código, pocos errores (< 300 líneas)

Manejo de estructuras de alto nivel

Uso de protocolos comunes

Del Buscador:

Armar un índice a partir de varios HTMLs

Traer un HTML y todos a los que enlaza

Servir la búsqueda a través de una interfaz Web

Estructura

Construímos el índice:

Varios threads: Repartidor, Constructor y Analizadores

El Repartidor alimenta los Analizadores con URLs

Cada Analizador trae el HTML y lo parsea

Envía los URLs que encuentra de vuelta al Repartidor

Envía las palabras al Constructor, que arma el índice

Servimos la búsqueda:

Armamos un servidor Web que ejecuta funciones Python

Presenta la página principal de búsqueda

Busca en el índice total y parcialmente

Muestra las búsquedas en otra página

Construímos el índice

Repartidor

Analizador

Constructor

Repartidor

class Repartidor:

...

def go(self):

while len(self.enlaces) > 0 or ...:

if sum(self.disponibles) > 0:

self.repartir()

...

parseados = self.qsRecibir[i].get(timeout=1)

parseados = [x for x in parseados if self.validar(x)]

self.enlaces.extend(parseados)

self.disponibles[i] = True

def repartir(self):

for i in range(self.cant):

if self.disponibles[i]:

if len(self.enlaces) > 0:

newlink = self.enlaces.pop()

self.qsEnviar[i].put(newlink)

self.disponibles[i] = False

Analizador

class Analizador(threading.Thread):

def __init__(self, qRepartIn, qRepartOut, qConstr):

...

def run(self):

while True:

info = self.qRepartIn.get()

...

(titulo, enlaces, contenido) = self.analizar(info)

self.qConstr.put((titulo, info, contenido))

self.qRepartOut.put(enlaces)

def analizar(self, url):

f = urllib.urlopen(url)

...

c = f.read()

p = Parser(url)

p.feed(c)

...

return (titulo, p.enlaces, p.contenido)

Parser

class Parser(htmllib.HTMLParser):

def start_a(self, data):

enl = [x[1].split("#")[0] for x in data

if x[0] == "href"]

self.agrega_enlaces(enl)

def start_frame(self, data):

enl = [x[1] for x in data if x[0] == "src"]

self.agrega_enlaces(enl)

def agrega_enlaces(self, enl):

enl = [urlparse.urljoin(self.base, x) for x in enl]

self.enlaces.extend(enl)

def handle_data(self, data):

partes = data.split()

self.contenido.extend(partes)

htmllib.HTMLParser.handle_data(self, data)

Constructor

class Constructor(threading.Thread):

def run(self):

while True:

info = self.cola.get()

if info is "quit":

self.dumpInfo()

return

self.armaIndice(*info)

def armaIndice(self, titulo, url, palabras):

dic = {}

for pal in palabras:

dic[pal] = dic.get(pal, 0) + 1

for (pal, cant) in dic.items():

enlaces = self.data.get(pal, {})

enlaces[url] = (cant, titulo)

self.data[pal] = enlaces

def dumpInfo(self):

cPickle.dump(dic, self.archout)

Servimos las búsquedas

Servidor

Página de búsqueda

Buscador

Resultados

Servidor

class ManejaPedidos(SimpleHTTPServer.SimpleHTTPRequestHandler):

def do_GET(self):

if self.path.find('?') > -1:

(base, busq) = self.path[1:].split('?')

pedido = cgi.parse_qs(busq, keep_blank_values=1)

accion = "run_%s" % base

if hasattr(self, accion):

f = getattr(self, accion)

contenido = f(pedido)

self.wfile.write(contenido)

return

SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)

return

def run_buscar(self, parametros):

request = parametros['textentry'][0]

return buscarIndice(request)

s = SocketServer.TCPServer(('',8080), ManejaPedidos)

s.serve_forever()

Página de búsqueda

<br><br> <center>

<img src=booscador.png border=0 alt="Booscador"

title="Booscador"> <br>

<form action=buscar name=f>

<table cellspacing=5 cellpadding=5> <tr> <td align=center>

<input maxLength=256 size=50 name=textentry value=""><br>

<input type=submit value="Booscar" name=booscar>

</td> </tr>

Buscador

class BuscarIndice(object):

def __init__(self, archivo):

self.indice = cPickle.load(open(archivo))

def busq_exacta(self, busq):

info = self.indice.get(busq, [])

return self.arma_tabla(info)

def busq_parcial(self, busq):

dic = {}

all = [v for (k,v) in self.indice.items() if busq in k]

for urlcoinc in all:

for (cant, tit, url) in urlcoinc:

dic[(tit, url)] = dic.get((tit, url), 0) + cant

info = [(c, t, u) for ((t, u), c) in dic.items()]

return self.arma_tabla(sorted(info, reverse=True))

def arma_tabla(self, info):

...

for (cant, tit, url) in info:

p.append('<tr><td><a href="%s">%s</a></td>' % (url, tit))

p.append("<td>%s</td></tr>" % cant)

return p

Resultados

Demo!

Lo probamos... ¡en vivo!

( les juro que hasta ayer funcionaba bien )

¿Preguntas?

¿Sugerencias?

¡Muchas gracias!

Facundo Batista

facundo@taniquetil.com.ar

www.taniquetil.com.ar

Decimal Structure: Finite numbers, Special values

Decimal Methods: as_tuple, quantize, to_eng_strings, to_integral, adjusted, same_quantum, normalize, compare, max and min, sqrt

Using Context: Structure of a Context, Getting the current context, Setting a new context, Standard contexts, DefaultContext

Context Methods: Standard arithmetic, Specific I, Specific II

Signals: What are Signals?, Dealing with Flags, Dealing with Traps, Clamped and DivisionByZero, Inexact and Rounded, InvalidOperation and Overflow, Subnormal and Underflow

Rounding: When rounding happens, Up & down, Ceiling & floor, Half up, down & even

Usage Cases: Do use Decimal: Financial, Do use Decimal: Easier life, Don't use Decimal: Speed / Accuracy, Don't use Decimal: Directly as Money

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Inexact:

>>> getcontext()

Context(..., flags=[Rounded, Inexact], ...)

Rounded: This signal is used to detect loss of significant digits.

>>> getcontext()

Context(..., flags=[Rounded], ...)

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

Needed if want to extend Decimal to trigonometry.

2005-03-06T16:13:33