Pensando en Python (III)

Embed Size (px)

Citation preview

  • 7/31/2019 Pensando en Python (III)

    1/8SOLO PROGRAMADORES n 120

    Introduccin

    Dada la popularidad de Internet, el desarrollo de apli-

    caciones con interfaz web, agnsticas de la platafor-ma donde se ejecute el cliente web (navegador), haexperimentado un crecimiento exponencial. A pesarde la menor sofisticacin de las interfaces web res-pecto a las interfaces grficas de aplicaciones desobremesa, su facilidad tanto de uso, dada la familia-ridad de los usuarios con el paradigma web, como susimplicidad de desarrollo, son razones suficientespara considerarlas como primera opcin en cualquierdesarrollo que una empresa acomete hoy en da.En las aplicaciones web, una sola instancia de lamisma ejecutndose en un servidor web (o varias enun cluster de servidores), es compartida por varios (enalgunos casos cientos o miles) de usuarios que acce-

    den a ella desde un cliente universal, el navegador deInternet. El principal cometido de una aplicacin webes crear pginas HTML (o en cualquier otro lenguajede marcado) de manera dinmica. Es decir, los datosestticos predefinidos de una pgina son combinadoscon datos generados por la lgica de la aplicacin uobtenidos de fuentes de datos en tiempo real, porejemplo de una base de datos. Durante la ejecucinconcurrente de las tareas requeridas simultneamen-te por los diferentes usuarios de la aplicacin web esfrecuente que se detecten conflictos de acceso ymodificacin a datos en el servidor. Adems, la aplica-cin web debe generar las pginas web, ejecutandotoda la lgica de negocio subyacente, de la manera

    ms rpida y eficiente posible. Es por tanto necesario,adoptar mecanismos en la parte servidora que agili-cen los accesos a datos y soporten transacciones, esdecir, conjuntos de operaciones fsicas relacionadassobre datos, que aparecen al cliente como una unidadlgica. Entran en juego aqu los llamados sistemasgestores de bases de datos (SGBD). La versin mscomnmente utilizada de los mismos son los sistemasrelaciones de bases de datos. En definitiva, servidoresweb y bases de datos relacionales conforman un bino-

    mio esencial en la creacin de toda aplicacin web.A continuacin, explicaremos cmo se puedencrear aplicaciones web en Python que acceden abases de datos relacionales. Como resultado deeste proceso transformaremos la aplicacin desobremesa tres en raya desarrollada durante lasdos anteriores entregas en una aplicacin web.

    Programacin web en Python

    Al tratarse Python de un lenguaje de cdigo abiertoexisten multitud de mdulos/libreras para realizarcualquier tarea programtica que imaginemos. En

    ocasiones, como es el caso de la programacin web,existen varios mdulos diferentes que de una mane-ra ms bsica o sofisticada nos permiten llevar a cabola misma tarea. Para comprobarlo no tenemos msque visitar el portal de Python, en su seccin deTemas/web (http://www.python.org/topics/web/). Allpodemos encontrar un largo listado de estos mdu-los, detallando sus diferentes funciones. A continua-cin enumeramos los ms destacados, clasificadossegn la categora de plataforma de desarrollo deaplicacin web a la que pertenecen: Programacin CGI Bsica: Mdulo CGI de la librera Standard de

    Python. CGI (Common Gateway Inteface) es

    un mecanismo estndar para la ejecucin decdigo ejecutable por un servidor web y laobtencin de los resultados de tal ejecucin.

    Mdulo Cookie para la creacin y procesa-miento de cookies en aplicaciones web. Unacookie es un mecanismo para mantener esta-do entre las peticiones HTTP de una sesinweb. Una cookie es una cabecera HTTP quepermite la identificacin unvoca en el servi-dor web del peticionario de la informacin.

    Programacin CGI Avanzada. En CGI, un nuevoproceso es creado por cada peticin HTTP recibi-da y eliminado cuando la peticin es resuelta. Laeficiencia es pobre. Esta es la razn por la que han

    22

    MIDDLEWARE

    Pensando en Python (III):

    3 en raya en la web

    Pensando en Python (III):

    3 en raya en la web

    En esta tercera entrega de la serie

    sobre Python aprenderemos a realizar

    aplicaciones web que acceden a

    bases de datos. Ilustraremos cmo

    Python representa una seria opcinpara el desarrollo de aplicaciones

    web mediante la extensin de la

    aplicacin de tres en raya

    desarrollada en las dos entregas

    anteriores.

    DIEGO LZ. DE IPIA GZ. DE ARTAZA (profesor del departa-mento de Ingeniera del Software de la facultad deIngeniera (ESIDE) de la Universidad de Deusto)

    Crearemos una

    aplicacin web

    que acceder a

    una base de datos

  • 7/31/2019 Pensando en Python (III)

    2/8SOLO PROGRAMADORES n 120

    aparecido numerosas tecnologas que per-miten una integracin superior con el servi-dor web subyacente, y lo ms importante,una mayor eficiencia. Ejemplos claros deestas tecnologas son PHP, Java Servlets yJSPs, y ASPs. En el caso particular de

    Python, la contribucin ms interesante aeste respecto es mod_python: mod_python es un mdulo Apache que

    integra el intrprete Python dentro delservidor, de modo que las aplicacionespueden ejecutarse de manera ms rpidaque CGI, retiene datos persistentes entrelas peticiones HTTP de una sesin y per-mite acceder a la parte interna de Apache.

    Servidores de aplicaciones.Van ms allde la simple generacin de pginas dinmi-cas y asisten al programador en otras tareasde la programacin de la lgica de negocio,tales como la persistencia de datos, la ges-

    tin de transacciones o la seguridad: Webware facilita una suite de compo-

    nentes Python para el desarrollo de apli-caciones web. Provee un servidor de apli-caciones, servlets, Python Server Pages(PSP), mapeo de objetos a bases de datosrelacional y organizador de tareas. Laarquitectura es muy modular, y permiteaadir tus propias extensiones.

    Zope, el Z Object Publishing Environment,proporciona una ORB (Object RequestBroker) HTTP que permite publicar e invo-car objetos Python en la web sin necesi-

    dad de ningn tipo de cdigo CGI o HTTPespecfico. Objetos complicados puedenser publicados con URLs que simulanjerarquas de objetos. Zope proporcionavarios componentes que pueden usarseen concierto o separadamente. Algunoscomponentes incluidos son: un paquetede plantillas HTML, un sistema de persis-tencia de objetos, una plataforma para lagestin de objetos va web, e incluso unservidor web sencillo.

    En este artculo nos concentraremos en elmdulo mod_python, que a juicio del autorrepresenta la manera ms sencilla y eficiente de

    implementar aplicaciones web en Python. Losservidores de aplicaciones como Zope repre-sentan una clara alternativa, y aunque tambintienen un rendimiento tan elevado o superior amod_python, su uso no es trivial y requeriransu exposicin mucho ms detallada.

    Integracin Apache/Python:mod_python

    Grisha Trubetskoy (http://www.ispol.com/home/grisha/) cre mod_python en 2003 con elpropsito de ofrecer un mdulo de extensin parael servidor web Apache (www.apache.org) que

    permitiese la generacin de pginas dinmicascon Python de una manera ms eficiente que eltradicional mdulo CGI. mod_python empotra elintrprete de Python dentro del servidor Apache.Con mod_python puedes escribir aplicacionesweb en Python que ejecutan muchas veces msrpido que los CGIs tradicionales, tienen acceso acaractersticas avanzadas tales como retenerconexiones a bases de datos entre conexionesHTTP y permiten acceder a la parte interna deApache. Con mod_python, el cdigo Python se

    ejecuta directamente dentro del servidor Apache,sin necesidad de que ste tenga que lanzar proce-sos externos o delegar las peticiones a servidoresde aplicaciones externos. mod_python se benefi-cia de las habilidades de Apache para aceptar yprocesar peticiones entrantes de una maneraescalable a la carga. El resultado es una platafor-ma que, segn Trubetskoy, puede procesar peticio-nes ms rpido que cualquier otra plataforma dedesarrollo web en Python. mod_python es: Un mdulo Apache recargable que empotra

    el intrprete de Python (libpython) prove-yendo la habilidad de ejecutar cdigoPython en el mismo proceso que Apache.

    Un manejador de las fases de procesamien-to de las peticiones HTTP en Apache, que per-mite implementar cualquier fase en Python.

    Tambin permite implementar filtros ymanejadores de conexiones en Python. Unfiltro HTTP intercepta de manera dinmicapeticiones y respuestas para transformar ousar la informacin contenida en las mismas.

    Una interfaz a un subconjunto de las APIsde Apache, permitiendo la invocacin defunciones internas del servidor desdePython. Esto permite acceder a informa-cin interna del servidor o de beneficiarsede facilidades del mismo como logeo.

    Una coleccin de herramientas para eldesarrollo de aplicaciones web. Provee unconjunto de manejadores de peticiones:Publisher (mapea URLs a objetos y funcio-nes dentro de mdulos Python), PSP (per-mite la creacin de Python Server Pages) yCGI (permite la programacin web confor-mando con el estndar CGI). Cada uno deestos manejadores ofrece una maneradiferente de desarrollar aplicaciones web,as como un conjunto de objetos y funcio-nes de utilidad para el procesamiento decookies, gestin de sesiones, y otros aspec-tos comunes en el desarrollo web.

    El mayor incoveniente de mod_python es ser espe-cfico a Apache, a diferencia de JSPs y PHP quepueden integrarse con diferentes servidores web.

    23

    MIDDLEWARE

    Pensando en Python (III): 3 en raya en la web

    LISTADO 2 Cdigo del fichero holasolop.psp

    LISTADO 1 Hay que incluir este cdigo XML en el fichero httpd.conf

    SetHandler mod_pythonPythonHandler mod_python.publisherPythonDebug On

    AddHandler mod_python .pspPythonHandler mod_python.pspPythonDebug On

    LISTADO 3Pgina de partida (index.html) de la aplicacin webTres en Raya

    Juego Tres en raya para Solop

  • 7/31/2019 Pensando en Python (III)

    3/8SOLO PROGRAMADORES n 120

    Instalando Apache y mod_pythonPara poder instalar mod_python es requisitoimprescindible la previa instalacin del

    intrprete de Python y el servidor webApache. Detalles sobre cmo instalar Pythontanto en Windows como UNIX fueron

    cubiertos en la primera entrega deesta serie.Apache ha sido el servidor ms popularen Internet desde 1996. En Octubre del2003, 64% de los servidores web enInternet usaban Apache. Para obtener la

    ltima versin de Apache es necesarioacceder a su pgina web: http://httpd.apache.org/. La mayora de lasdistribuciones Linux ya traen preinstala-do este servidor bien en su versin 1.3 o2.0 (la ltima y la que utilizaremos eneste artculo). Alternativamente, serecomienda que utilices tu gestor depaquetes Linux favorito para conseguiruna copia o bjate el cdigo fuente dehttp://httpd.apache.org/download.cgi ysigue las instrucciones de compilacinincluidas. Si eres un usuario deWindows bjate el fichero de instala-

    cin apache_2.xxx-win32-x86-xxx.msiy haz doble clic sobre l (el CD-ROMadjunto incluye la versin de Apachepara Windows).mod_python puede obtenerse dehttp://httpd.apache.org/modules/python-download.cgi. Los usuarios deWindows deben ejecutar el fichero.exe suministrado que instalarmod_python en su sistema. Los usua-rios de UNIX pueden bajarse el cdigofuente y las instrucciones de compila-cin del mismo lugar. En la prepara-

    cin de este artculo hemos usado laversin 3.0 de mod_python (el CD-ROM adjunto incluye la versin demod_python para Windows).

    Configurando Apache ymod_pythonUna vez instalado Apache ymod_python tan slo resta modificarel principal fichero de configuracinde Apache, ubicado en /conf/httpd.conf:1.- Al final del bloque de sentenciasLoadModule aadir la siguiente:

    LoadModule python_module modules/

    mod_python.so

    2.- Despus del bloque XML iniciadopor el elemento Directory y corres-pondiente al directorio htdocs, direc-torio raz del que cuelgan, por defec-to, los documentos HTML estticos enApache, colocar los bloques Directorydel listado 1, reemplazando por la ruta

    de instalacin de Apache en tu mquina.Con las definiciones mostradas en el lista-do 1 indicamos que debajo del subdirecto-

    24

    MIDDLEWARE

    LISTADO 5 Cdigo principal de web /cgi-bin/psp/tresenrayaweb.py

    import tresenraya

    NO_GANADOR = -1EMPATE = 0GANA_JUGADOR = 1PIERDE_JUGADOR = 2

    class JuegoTresEnRayaWeb(tresenraya.JuegoTresEnRaya):# falta el constructor y algunos mtodos, mirar cdigo completo en CD...def select_casilla(self, x, y):

    if not self.jugar(x, y):return self.ganador

    else:return NO_GANADOR

    def jugar(self, x, y):if self._JuegoTresEnRaya__casillasMarcadas < 9:

    if self._JuegoTresEnRaya__casillero[x][y] == None:

    self._JuegoTresEnRaya__casillero[x][y]=self._JuegoTresEnRaya__marcaJugadorself._JuegoTresEnRaya__casillasMarcadas += 1self.__marcarCasilla(x, y, o.png)if self._JuegoTresEnRaya__hayGanador():

    self._JuegoTresEnRaya__registro.registrarVictoria(self._JuegoTresEnRaya__nombreUsuario)

    self.ganador = GANA_JUGADORreturn False

    elif self._JuegoTresEnRaya__casillasMarcadas == 9:self._JuegoTresEnRaya__registro.registrarEmpate(

    self._JuegoTresEnRaya__nombreUsuario)self.ganador = EMPATEreturn False

    casillaIndex = self._JuegoTresEnRaya__elegirMarcaMaquina()self._JuegoTresEnRaya__casillero[casillaIndex[0]][casillaIndex[1]] =

    self._JuegoTresEnRaya__marcaMaquinaself._JuegoTresEnRaya__casillasMarcadas += 1

    self.__marcarCasilla(casillaIndex[0], casillaIndex[1], x.png)if self._JuegoTresEnRaya__hayGanador():

    self._JuegoTresEnRaya__registro.registrarPerdida(self._JuegoTresEnRaya__nombreUsuario)

    self.ganador = PIERDE_JUGADORreturn False

    elif self._JuegoTresEnRaya__casillasMarcadas == 9:self._JuegoTresEnRaya__registro.registrarEmpate(self._JuegoTresEnRaya__nombreUsuario)

    self.ganador = EMPATEreturn False

    return True

    LISTADO 4 Lgica de control de /cgi-bin/psp/tresenraya.psp

  • 7/31/2019 Pensando en Python (III)

    4/8SOLO PROGRAMADORES n 120

    rio python de cgi-bin, directoriopor defecto del que cuelgan losscripts CGI en Apache, colocare-mos programas Python que gene-rarn pginas HTML siguiendo elmodelo del manejador de peticio-

    nes Publisher. Con la segundadirectiva Directory indicamos quebajo el directorio psp colocaremosscripts en formato Python ServerPages (PSP).

    Python Server Pages enmod_pythonPython Server Pages (PSP) es unmecanismo para incluir sentenciasPython en documentos HTML o XML.El servidor interpreta el cdigo Pythonincluido para producir el documentoHTML o XML enviado al cliente. Este

    mecanismo se ha hecho popular atravs de otras herramientas bienconocidas como JSP, PHP o ASP.Es importante remarcar que mezclarcdigo fuente Python en mitad de undocumento HTML es objeto de ciertacontroversia. Algunos ingenieros delsoftware consideran incluir cdigo enmitad de un documento HTML unamala prctica de programacin, al vio-lar el paradigma Modelo-Vista-Controlador, introduciendo lgica denegocio en la capa de presentacin. A pesar de

    no ser tan buena prctica, los millones de pro-gramadores PHP que exitosamente utilizan esteparadigma demuestran que existe grandemanda por este estilo de programacin web.No entraremos en discusiones dogmticas eneste artculo, esto es un artculo sobre Python yno sobre patrones de diseo.La sintaxis de PSP es similar a la original deJSP, delimitando el cdigo Python por mediode los smbolos . De igual modo aJSP, PSP tiene cuatro tipos de entidades: Cdigo. Representa el cdigo fuente

    Python que contiene la lgica de cmo lasalida final es producida. Est delimitado

    por los cdigos de escape . Expresiones. Es cdigo fuente Python

    cuyo resultado en forma de un string

    forma parte de la salida final. Est delimi-

    tado por los cdigos de escape

    . Directivas. Son instrucciones especialespara el procesador PSP. Son delimitadaspor los cdigos . Actualmentemod_python slo soporta la directiva,que reemplazar esta directiva por elcontenido del fichero nombre-fichero.

    Comentarios. En PSP, son eliminados porel procesador PSP, y son delimitados porlos smbolos .

    La parte ms complicada de la programacinPSP es la gestin de la tabulacin sintctica dePython. El intrprete de PSP recuerda la ltima

    tabulacin Python usada a lo largo del cdigoHTML, y deberemos ajustar nuestro cdigoPython a la misma. Para simplificar esta tarea

    es recomendable usar comentarios que hagan

    el cdigo ms legible. Por ejemplo:

    25

    MIDDLEWARE

    Pensando en Python (III): 3 en raya en la web

    Figura 1. Nuestra primera aplicacin web en PSP.

    Figura 2. Pantalla web generada por el

    script tresenraya.psp.

    LISTADO 6 Cdigo de /cgi-bin/psp/login.psp

    Nombre usuario:

    Contrasea:

  • 7/31/2019 Pensando en Python (III)

    5/8SOLO PROGRAMADORES n 120

    ... cdigo html ...

    Hola Solop en el PSP demod_pythonEn el listado 2 mostramos cmo sepodra realizar una simple pgina PSPque reproduce el mensaje Hola Solopal invocar la URL http://local-host:8080/cgi-bin/psp/holasolop.psp.Si se le aade a la URL el sufijo ?nom-bre=lectores+Solop, el resultadogenerado sera Hola, Lectores Solop.En la figura 1 se visualiza el resultadode realizar sta ltima invocacin.

    Variables globales

    Existen varias variables accesibles entiempo de ejecucin de una pginaPSP. Estas variables pueden ser utiliza-das directamente, sin habrseles asignado nin-gn valor previamente: req, el objeto Request de mod_python.

    Toda la funcionalidad avanzada demod_python es disponible a travs deeste objeto en una pgina PSP.

    psp, corresponde a una instancia del obje-to PSPInstance, que permite acceder a unaAPI especfica de PSP. Ofrece los siguientesmtodos:

    set_error_page(filename), permiteespecificar el nombre de una pginaPSP a invocar cuando ocurre un erroren Python.

    apply_data(object), invocar el obje-to object, pasndole como argumen-tos los campos del formulario y devol-viendo el resultado. Si ests familiari-zado con JSP funciona comosetProperty. Por ejemplo, dado elsiguiente objeto:

    class Coche:

    def __init__(self, color):

    self.color = color

    Entonces, una pgina PSP invocada comoresultado de una ejecucin de un formu-lario conteniendo un campo con nombre

    color, podra hacer lo siguiente:

    Esta sentencia invocara el cons-tructor del objeto Coche, pasando elvalor del campo del formulariocolor. Como resultado, una instan-cia de Coche sera asignada a lavariable coche. redirect(location), puede utili-zarse para redireccionar entre pgi-nas PSP. Debe invocarse como pri-mera sentencia en una pgina, no se

    puede producir una redireccin despusde haber datos de salida al navegador.

    form, corresponde a los campos de unformulario en formato diccionario (obje-to mod_python.FieldStorage).

    session, si PSP detecta que una pginahace referencia a la variable session, auto-mticamente crear un objeto de tipo

    mod_python.Session, que generar cookiesde sesin y permitir mantener estadoentre las invocaciones de una peticin.

    Para ms informacin sobre los objetos defi-nidos por mod_python, consultar su manualdisponible en http://www.modpython.org/live/current/doc-html/.

    Aadiendo una interfaz web a laaplicacin Tres en Raya

    Una vez conocida la teora bsica sobre cmocrear y usar objetos mod_python dentro deun PSP, vamos a ilustrar su uso transforman-

    26

    MIDDLEWARE

    LISTADO 7 Cdigo de /cgi-bin/psp/estadisticas.psp

    Las estadsticas de partidas jugadas por son:

    GanadasEmpatadasPerdidas

    Inicianueva partida
    Login como otro usuario

    Figura 3. Pantalla web generada por script login.psp.

    LISTADO 8 Cdigo SQL para crear la base de datos tresenraya

    CREATE DATABASE tresenraya;GRANT ALTER, SELECT,INSERT,UPDATE,DELETE,CREATE,DROP

    ON tresenraya.*TO tresenraya@localhostIDENTIFIED BY tresenraya;

    CREATE TABLE usuario (nombreUsuario varchar(250) not null primary key,password varchar(250)

    );CREATE TABLE estadistica(

    nombreUsuario varchar(250) not null primary key referencesusuario(nombreUsuario),

    ganadas int(11) default 0,empatadas int(11) default 0,perdidas int(11) default 0

    );

  • 7/31/2019 Pensando en Python (III)

    6/8SOLO PROGRAMADORES n 120

    do nuestra aplicacin de tres en raya en unaaplicacin web.En Apache los documentos estticos se guar-dan, por defecto, en su directorio htdocs. Paranuestra aplicacin crearemos un subdirectoriotresenraya debajo de htdocs, y colocaremosall un fichero index.html que apunta al fiche-ro .psp que acta como controlador de la apli-

    cacin tres en raya. Adems, crearemos unsubdirectorio images donde guardaremos losficheros .png que indican que una celda noest marcada (blank.png), est marcada por eljugador (o.png) o la mquina (x.png). El listado3 muestra el fichero index.html que incrustaun marco (frame) que contiene otro marco deigual tamao. El marco interior ir cambiandode contenido durante la ejecucin de la aplica-cin, mientras que el marco exterior permane-cer haciendo que la URL que aparece en elnavegador no cambie. Es un buen truco paraevitar que el usuario de la aplicacin web sepaqu PSP se est ejecutando en cada ocasin, e

    incluso con qu tecnologa se ha desarrolladola aplicacin.Por otra parte, debajo del directorio cgi-bin,donde normalmente se colocan ficheros quegeneran documentos XML de manera dinmica,creamos el subdirectorio psp, en el queguardamos los siguientes ficheros: tresenraya.psp: script PSP que

    visualiza el tablero del juego de tresen raya y acta tambin comocontrolador del resto de PSPs. Si unusuario intenta acceder a este PSPy no ha hecho login previamenteser redirigido a login.psp. Por otrolado, si un usuario que ha hechologin desea ver las estadsticas deresultados de las partidas que hajugado, este PSP le redirigir aestadisticas.psp. El listado 4 mues-tra la lgica de control correspon-diente a este script. Hace que seredireccione a otros PSPs o se invo

    que al mtodo select_casilla delobjeto JuegoTresEnRayaWeb, defi-nido en tresenrayaweb.py. En lafigura 2 podemos ver el resultadode haber invocado este PSP hastacompletar una partida de tres en

    raya. tresenrayaweb.py: define la clase

    JuegoTresEnRayaWeb que heredade la clase JuegoTresEnRaya, imple-mentada en las anteriores entregas.Simplemente sobrescribe su mto-do jugar() y declara un nuevo mto-do pblico select_casilla. En tresen-raya.psp se aade a la variablesesin una instancia de esta clase.El listado 5 muestra las partes msimportantes de la implementacinde esta clase.

    login.psp: script PSP que comprue-

    ba en primer lugar si existe una ins-tancia del objeto de tipoRegistroJugadores (o una de sussubclases), implementada en lasanteriores entregas, en la variableglobal session. Si no es as la crea. Sien la invocacin se han pasado losparmetros nombreUsuario y clave,correspondientes a un usuarioregistrado, se redirecciona a tresen-raya.psp. El listado 6 muestra elcontenido de este PSP. Es impor-tante resaltar que login.psp crea

    una instancia de la claseRegistroJugadoresDB que deriva deRegistroJugadores, aunque en estaocasin guarda los datos en unabase de datos. En la siguiente sec-cin se describir esta clase en msdetalle. En la figura 3 se puede verel resultado de invocar el scriptlogin.psp.

    estadisticas.psp: script PSP que visualiza enuna tabla HTML las partidas ganadas, empa-

    27

    MIDDLEWARE

    Pensando en Python (III): 3 en raya en la web

    Figura 4. Pantalla web generada por el scriptestadisticas.psp.

    LISTADO 9 Clase RegistroJugadoresDB

    # importar mdulos especficos de MySQL: MySQLdbimport MySQLdb, string, _mysql, _mysql_exceptions, tresenrayaclass RegistroJugadoresDB(tresenraya.RegistroJugadores):

    def __init__(self):tresenraya.RegistroJugadores.__init__(self)db=MySQLdb.connect(host=localhost, user=tresenraya,

    passwd=tresenraya, db=tresenraya)self.cursor = db.cursor()# Asegurarse que si no existe un usuario solop se aadausuarioSolop = self._executeSQLCommand(

    select * from usuario where nombreUsuario=solop)# lgica para aadir usuario solop si no existe

    def guardarEnDB(self):# Guardar por cada usuario sus detalles de login y sus estadsticasfor usuario in self._RegistroJugadores__jugadores.keys():

    try:self._executeSQLCommand(insert into usuario values( + usuario +

    , + self._RegistroJugadores__jugadores[usuario] + ))except:

    self._executeSQLCommand(update usuario set password= +self._RegistroJugadores__jugadores[usuario] + where nombreUsuario= + usuario + )

    ...

    def _executeSQLCommand(self, command):# si la consulta devuelve resultados lo har como una lista de tuplas (filas)# cada elemento de la tupla ser una columnaresultado = []command = string.strip(command)if len(command):

    try:resultCode = self.cursor.execute(command) # Ejecuta el comandoif string.lower(command).startswith(select): # si es una select ...

    filas = self.cursor.fetchall() # recuperar todos los resultadosfor fila in filas:

    contenidoFila = []for columna in fila:

    if columna == None:contenidoFila.append(None)

    else:

    contenidoFila.append(columna)resultado.append(tuple(contenidoFila))

    except _mysql_exceptions.ProgrammingError, e:print esys.exit()

    return resultado

  • 7/31/2019 Pensando en Python (III)

    7/8SOLO PROGRAMADORES n 120

    tadas y perdidas por el jugador que ha hechologin. El listado 7 muestra el cdigo fuentede este PSP. En la figura 4 se puede ver elresultado de invocar estadisticas.psp. En vezde producir una simple tabla HTML podra-mos haber generado una imagen en forma-

    to PNG conteniendo un grfico de barrascomo hicimos en la versin del programa enwxPython. Para ello podramos haber utiliza-do por ejemplo el modulo matplotlib, dispo-nible en http://matplotlib. sourceforge.net

    Programacin de bases dedatos en Python

    Al igual que Java ofrece el estndar JDBC para laprogramacin de bases de datos, Python hace lopropio con su DB-API. Con esta API Python con-sigue aislar el cdigo fuente de la base de datossubyacente. El cdigo Python se acomodar a

    los interfaces de la DB-API, mientras que unaimplementacin de esta API para cada sistemade bases de datos, traducir invocaciones deDB-API en llamadas de la base de datos. En laseccin del portal Python, temas/basesdedatos(http://www.python.org/topics/database/) sepuede encontrar informacin detallada sobreesta API.

    DB-APIA continuacin enumeramos los principalesinterfaces ofrecidos por la DB-API: Para conectarnos a una base de datos

    usamos el mtodo connect del mdulo de

    base de datos utilizado que devuelve unobjeto de tipo conection.

    El objeto conection ofrece el mtodo cur-sor() que sirve para recuperar un cursor de laBD. Otros mtodos definidos en connectionson close(), commit(), rollback() y cursor().

    El objeto cursor define entre otros lossiguientes mtodos: execute() nos permite enviar una sen-

    tencia SQL a la BD. fetchone() recupera una fila. fetchall() recuperar todas las filas.

    Como se ha comentado, cada sistema relacio-nal de bases de datos ha de ofrecer una imple-mentacin de DB-API. Dada la naturaleza decdigo abierto de Python, hay varios mdulosque implementan este estndar: DCOracle (http://www.zope.org/Products/

    DCOracle/) creado por Zope para Oracle MySQLdb (http://sourceforge.net/projects/

    mysql-python) para MySQL. PyDB2 (http://sourceforge.net/projects/

    pydb2) para DB2. Y otros muchos msNosotros utilizaremos la implementacin deDB-API para MySQL, una de las bases de datosde cdigo abierto ms populares en Internet.

    MySQL y MySQLdbMySQL fue creada por la empresa sueca MySQLAB (www.mysql.com). MySQL es una parte esen-cial del proyecto LAMP (Linux, Apache, MySQL,PHP/Perl/Python), una pila de herramientas desoftware abierto para desarrollar aplicaciones de

    empresa que est experimentando un gran creci-miento. Cada vez ms compaas utilizan LAMPcomo una alternativa a software propietario.La instalacin de MySQL es muy sencilla tantoen Linux como Windows. En la siguiente URL sepueden obtener RPMs y ejecutables para insta-

    lar la ltima versin de MySQL (4.0) tanto enLinux como Windows: http://dev.mysql.com/downloads/mysql/4.0.html.Por su parte, la instalacin de MySQLdb,implementacin para MySQL de la DB-API, estambin trivial. Simplemente accede a supgina web (http://sourceforge.net/projects/mysql-python) y usa el instalador provistopara Windows o el RPM para Linux.

    Usando MySQL para la aplicacinTres en Raya

    Cmoltimo paso en nuestro proceso de mejora

    de la aplicacin Tres en Raya, vamos a guardar losdetalles de los jugadores autorizados y las esta-dsticas sobre los resultados de sus partidas enuna base de datos. El listado 8 ilustra cmo crearen MySQL una base de datos de nombre tresen-raya, a la que podemos hacer login de maneralocal con el usuario tresenraya y clave tresenraya,y que define las tablas usuario y estadistica.Una vez creada la base de datos, creamos unanueva clase en Python a la que llamamos,RegistroJugadoresDB, que hereda de la claseRegistroJugadores que hemos ido utilizando yextendiendo desde el primer artculo. El listado 9

    muestra un fragmento de la implementacin deesta clase, dentro del mdulo RegistroJugadoresDB.Obsrvese que el mdulo MySQLdb es lo primeroque se importa en este mdulo. El mtodoexecuteSQLCommand invoca toda operacin SQLsobre la base de datos. Para ms detalles, consultarel cdigo incluido en el CD-ROM.Finalmente slo nos resta indicar cmo inte-grar el uso de esta clase dentro de nuestrocdigo PSP. El listado 10 muestra cmo al fina-lizar una partida se proceder a guardar losdetalles de los usuarios y los resultados de laspartidas que han jugado, invocando el mtodode RegistroJugadoresDB, guardarEnDB().

    Conclusiones

    En esta tercera entrega de la serie sobrePython hemos aprendido cmo desarrollaraplicaciones web que acceden a bases dedatos a travs de los mdulos mod_python yMySQLdb, respectivamente. En la siguienteentrega concluiremos nuestro estudio dePython, ilustrando el potencial del mismo en elprocesamiento de XML y mirando a dos pri-mos hermanos de Python, JPython, la imple-mentacin Java de Python e IronPython, laimplementacin .NET de Python.

    28

    MIDDLEWARE

    LISTADO 10 Guardando estadsticas en /cgi-bin/psp/tresenraya.psp

    Ha habido empate!

    El jugador ha ganado!

    La mquina ha ganado!

    Inicia nueva partida
    Ver estadsticas jugador
    Login como otro usuario

  • 7/31/2019 Pensando en Python (III)

    8/8