pensando en python (y iv): xml, java e ia pensando en python (y

7
SOLO PROGRAMADORES nº 121 Introducción En los últimos años el estándar XML (eXtensible Markup Language) se ha establecido como el princi- pal mecanismo para el intercambio de datos entre aplicaciones. XML es un metalenguaje que permite diseñar otros lenguajes. Algunos ejemplos de len- guajes derivados de XML son WML, MathML o XHTML. Con XML cualquiera puede desarrollar su propio lenguaje de etiquetas adecuado al tipo de aplicación que más le convenga. Un documento XML puede ser fácilmente procesado y sus datos manipu- lados, por medio de APIs estándar disponibles en len- guajes como Java, C, C++, C# y, por supuesto, Python. En esencia, XML define datos portables, al igual que Python o Java definen código portable. Por otra parte, el lenguaje de programación Java ha experimentado desde su nacimiento en 1995 un cre- cimiento extraordinario. En los últimos 10 años Java no sólo ha ido madurando como lenguaje de progra- mación si no que gracias al ofrecimiento gratuito por parte de Sun de la JDK (Java Development Kit) su adopción ha sido espectacular. Como resultado ha habido numerosísimas contribuciones de código abierto que facilitan el desarrollo de cualquier pro- blema informático que podamos concebir. Jython, la implementación Java de Python, fue creado para poder aprovechar todas estas contribuciones del mundo Java y tener acceso a su funcionalidad desde la elegante sintaxis de Python. En este artículo describiremos cómo programar apli- caciones que usan XML y acceden a paquetes des- arrollados en Java desde Python. Concluiremos con una discusión del algoritmo de inteligencia artificial MiniMax que permitiría a la máquina ser un contrin- cante de entidad en el juego de tres en raya. XML En las próximas líneas vamos a hacer un repaso de la tecnología XML, aunque este tema ha sido tratado con profundidad en ediciones anteriores de Sólo Programadores. Si el lector quiere ampliar lo aquí expuesto, puede consultar los números 110, 111, 114, 115 y 116. XML no es sólo un lenguaje de lenguajes, es también un conjunto de tecnologías que permiten su repre- sentación y procesamiento, tales como XPath, XLink, XPointer o XML. La especificación de XML 1.0 puede encontrarse en la dirección de Internet http://www.w3.org/TR/REC-xml. Un documento XML está estructurado en los siguientes componentes: Instrucciones de procesamiento (processing instructions – PI). Las PI son instrucciones para el procesador del documento XML. El prólogo del documento es una PI obligatoria: <?xml version=”1.0” encoding=”iso-8859-1”?> Declaraciones de tipo de documento. Especifican la estructura y sintaxis de un docu- mento XML a través de una gramática bien en la forma de un DTD (Document Type Definition) o un Schema. Se declaran en un documento en el siguiente modo: <!DOCTYPE <elemento-raíz> SYSTEM “<fichero-con-dtd”> A través del DTD una instancia de un docu- mento puede ser validada contra la gramática que define los elementos y posición de los mis- mos en un documento. Comentarios. Sirven para realizar anotaciones útiles al autor del documento. Un ejemplo sería: <!— Esto es un comentario —> Elementos. Aportan estructura semántica al documento. Se delimitan por etiquetas de apertura y cierre o vienen sin elementos inte- riores (etiquetas vacías como <br/>). Las eti- quetas de apertura y las vacías suelen venir 36 MIDDLEWARE Pensando en Python (y IV): XML, Java e IA Pensando en Python (y IV): XML, Java e IA Acabamos esta serie sobre Python examinando su capacidad para el procesamiento de XML e introduciendo Jython, la implementación Java de Python. También discutiremos una implementación más inteligente del juego de tres en raya que usa un algoritmo de inteligencia artificial. DIEGO LZ. DE IPIÑA GZ. DE ARTAZA (profesor del Departamento de Ingeniería del Software de la Facultad de Ingeniería (ESIDE) de la Universidad de Deusto) XML define datos portables y Python define el código fuente

Upload: vutram

Post on 02-Feb-2017

270 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

Introducción

En los últimos años el estándar XML (eXtensibleMarkup Language) se ha establecido como el princi-pal mecanismo para el intercambio de datos entreaplicaciones. XML es un metalenguaje que permitediseñar otros lenguajes. Algunos ejemplos de len-guajes derivados de XML son WML, MathML oXHTML. Con XML cualquiera puede desarrollar supropio lenguaje de etiquetas adecuado al tipo deaplicación que más le convenga. Un documento XMLpuede ser fácilmente procesado y sus datos manipu-lados, por medio de APIs estándar disponibles en len-guajes como Java, C, C++, C# y, por supuesto,Python. En esencia, XML define datos portables, aligual que Python o Java definen código portable.Por otra parte, el lenguaje de programación Java haexperimentado desde su nacimiento en 1995 un cre-cimiento extraordinario. En los últimos 10 años Javano sólo ha ido madurando como lenguaje de progra-mación si no que gracias al ofrecimiento gratuito porparte de Sun de la JDK (Java Development Kit) suadopción ha sido espectacular. Como resultado hahabido numerosísimas contribuciones de códigoabierto que facilitan el desarrollo de cualquier pro-blema informático que podamos concebir. Jython, laimplementación Java de Python, fue creado parapoder aprovechar todas estas contribuciones delmundo Java y tener acceso a su funcionalidad desdela elegante sintaxis de Python.En este artículo describiremos cómo programar apli-caciones que usan XML y acceden a paquetes des-

arrollados en Java desde Python. Concluiremos conuna discusión del algoritmo de inteligencia artificialMiniMax que permitiría a la máquina ser un contrin-cante de entidad en el juego de tres en raya.

XML

En las próximas líneas vamos a hacer un repaso de latecnología XML, aunque este tema ha sido tratadocon profundidad en ediciones anteriores de SóloProgramadores. Si el lector quiere ampliar lo aquíexpuesto, puede consultar los números 110, 111, 114,115 y 116.XML no es sólo un lenguaje de lenguajes, es tambiénun conjunto de tecnologías que permiten su repre-sentación y procesamiento, tales como XPath, XLink,XPointer o XML. La especificación de XML 1.0 puedeencontrarse en la dirección de Internethttp://www.w3.org/TR/REC-xml. Un documento XMLestá estructurado en los siguientes componentes:

Instrucciones de procesamiento (processinginstructions – PI). Las PI son instrucciones parael procesador del documento XML. El prólogodel documento es una PI obligatoria:<?xml version=”1.0” encoding=”iso-8859-1”?>

Declaraciones de tipo de documento.Especifican la estructura y sintaxis de un docu-mento XML a través de una gramática bien enla forma de un DTD (Document TypeDefinition) o un Schema. Se declaran en undocumento en el siguiente modo:<!DOCTYPE <elemento-raíz> SYSTEM “<fichero-con-dtd”>

A través del DTD una instancia de un docu-mento puede ser validada contra la gramáticaque define los elementos y posición de los mis-mos en un documento.Comentarios. Sirven para realizar anotacionesútiles al autor del documento. Un ejemplo sería:<!— Esto es un comentario —>

Elementos. Aportan estructura semántica aldocumento. Se delimitan por etiquetas deapertura y cierre o vienen sin elementos inte-riores (etiquetas vacías como <br/>). Las eti-quetas de apertura y las vacías suelen venir

36

MIDDLEWARE

Pensando en Python (y IV):XML, Java e IAPensando en Python (y IV):XML, Java e IA

Acabamos esta serie sobre Pythonexaminando su capacidad para elprocesamiento de XMLe introduciendo Jython, laimplementación Java de Python.También discutiremos unaimplementación más inteligente deljuego de tres en raya que usa unalgoritmo de inteligencia artificial.

DIEGO LZ. DE IPIÑA GZ. DE ARTAZA (profesor delDepartamento de Ingeniería del Software de la Facultadde Ingeniería (ESIDE) de la Universidad de Deusto)

XML definedatos portablesy Python defineel código fuente

Python 121.qxd 17/12/04 01:06 Página 36

Page 2: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

acompañadas de atributos, que parame-trizan el elemento.Referencias a entidades. Sirven parainsertar un determinado contenido defi-nido previamente. Por ejemplo:<!ENTITY Empresa “Universidad de Deusto”>...<pie>Creado por &Empresa; </pie>

Secciones CDATA. Contienen texto queno queremos sea procesado por el parserde XML. Por ejemplo:<![CDATA[<saludo>Hola, mundo!</saludo>]]>

Las razones fundamentales del éxito de XMLson:

Permite etiquetar los datos con su signi-ficado (self-describing data).Estructurar la información de acuerdo alas necesidades de la aplicación.Tratar automáticamente la información através de procesadores libremente dispo-nibles, que se ajustan a APIs estándar.

XML es la base de una nueva generación deaplicaciones web, siendo un estándar para elintercambio de datos. Entre otras cosas XMLse utiliza como formato de datos en sitios webpara separar contenido y presentación, comomedio de comunicación para el intercambiode datos entre organizaciones o para la trans-misión de mensajes en servicios web (SOAP).

Procesamiento XML

La popularidad de XML estriba en no tener quecrear un nuevo compilador por cada lenguaje derepresentación de datos que queremos diseñar.Las herramientas que llevan a cabo la validaciónléxica y sintáctica de los documentos y su trans-formación en una representación manejable porprogramas vienen ya dados. A cambio, los dise-ñadores de nuevos tipos de documentos XMLsólo deben seguir las restricciones que un docu-mento XML bien formado debe cumplir:

Debe tener un prólogo.Debe tener una etiqueta (elemento) raíz.Las etiquetas se hallan correctamenteanidadas.Se usan caracteres válidos y bien aplicados.Los valores de los atributos vienen ence-rrados entre comillas.

La industria utiliza tres estándares principa-les para el procesamiento de documentosXML: SAX, DOM y XSL. A continuación, pasa-mos a describirlos en más detalle.

Procesamiento de XML con SAXSAX es el estándar “de facto” para el procesa-miento de XML basado en eventos. Fue definidopor David Megginson, siendo su especificacióndisponible en http://www.megginson.com/SAX.No es un analizador XML, si no que define unainterfaz común implementada por los analiza-dores XML SAX. Un analizador SAX genera unevento por cada componente significativo deldocumento detectado. Por ejemplo el comienzoo final del documento, o el comienzo y final delelemento. Un programador que usa SAX debeimplementar manejadores de los eventos notifi-cados. SAX opera sobre un documento leyendosecuencialmente de principio a fin, sin cargartodo el documento en memoria. Presenta comoprincipal ventaja una gran eficiencia en cuantoal tiempo y la memoria empleados en el análisis.La principal desventaja de SAX es que tenemosque mantener estado intermedio, a diferenciade otros estándares como DOM.

Procesamiento de XML con DOMUn documento XML es para DOM un árbol denodos, donde cada nodo representa a un ele-mento XML. Los elementos hijos y el textocontenido dentro de un elemento son subno-dos. La especificación DOM es un estándarW3C disponible en http://www.w3.org/DOM/.La principal ventaja de DOM es que permiteacceder a datos en función de la jerarquía deelementos, así como modificar el contenidode los documentos e incluso crearlos desdecero. La principal desventaja es el coste entiempo y memoria que conlleva construir elárbol. A diferencia de SAX que efectúa unapasada del documento de izquierda a dere-cha y de arriba abajo, carga todo el docu-mento XML en memoria. Para documentoslargos la demanda de memoria puede seringente. Como consecuencia de ello, DOM noes adecuado para efectuar procesamiento deXML en dispositivos empotrados con pocacapacidad de cómputo y memoria.

Procesamiento de XML con XSLDada la diversidad de lenguajes de presenta-ción (WML, HTML, cHTML), existen dos alter-nativas para desarrollar aplicaciones basa-das en páginas:

Desarrollar versiones de los procesos degeneración de presentación (JSP, ASP,CGI,..) para cada lenguaje de marcado final.Desarrollar sólo una versión que genereXML y conversores de XML a los lengua-jes de presentación.

El lenguaje de programación XSL fue diseña-do para responder al segundo enfoque, y ellector debería ser conocedor de ello, puesXSL-FO es objeto de nuestro estudio desdehace unos meses. XSL consta de dos partes:

XML Stylesheet Transformation Language(XSLT)XSL Formatting Language (XSL-FO)

XSLT es el componente de XSL que transfor-ma un documento XML en otro documentoXML. XSL-FO formatea y estiliza documen-tos en varios modos. La especificación deXSLT se encuentra disponible enhttp://www.w3.org/TR/xslt. Las principalesventajas de XSLT son:

No asume un único formato de salida dedocumentos.Permite manipular de muy diversasmaneras un documento XML: reordenarelementos, filtrar, añadir, borrar, etc.

Las desventajas de XSLT son:Su utilización es más compleja que unlenguaje de programación convencional.Consume bastante memoria y capacidadde proceso, usa DOM por debajo.

Programación XML en Python

Para ilustrar el poder de Python en la progra-mación de aplicaciones XML vamos a consi-derar el fragmento de código XML del listado1. Este listado corresponde a la cartelera detodos los cines en una ciudad. Por cada cinelistado, incluimos las películas que se mues-tran en él y los horarios de sus sesiones.

Procesamiento SAX en Python

El soporte para SAX en Python es ofrecido porel módulo “xml.sax” de la librería estándar dePython (http://docs.python.org/lib/module-xml.sax.html). Este módulo define una funciónprincipal, “make_parser()”, a través de la cualcrea y devuelve un objeto de tipo “XMLReader”,que corresponde con un procesador SAX. Ladefinición de esta clase se encuentra en elmódulo “xml.sax.xmlreader”. El módulo“xml.sax.handler” define manejadores de even-tos para SAX. Para asignar un manejador deeventos a un procesador SAX se invoca elmétodo “setContentHandler(handler)”, donde“handler” es una referencia a un objeto queimplementa la interfaz “xml.sax.hander.ContentHandler”. Esta interfaz define métodostales como “startdocument” o “endelement”que son invocados cuándo se genera un even-

37

MIDDLEWAREPensando en Python (y IV): XML, Java e IA

Python 121.qxd 17/12/04 01:06 Página 37

Page 3: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

to al entrar en una parte significativa del docu-mento. El listado 2 muestra un ejemplo decódigo Python que procesa el fichero“Cartelera.xml” para contar el número de ele-mentos y atributos XML encontrados en él.Tanto el documento XML (Cartelera.xml) comoel script Python (ElementCounterSAX.py) estándisponibles en el CD-ROM que acompaña a larevista. La figura 1 muestra el resultado de laejecución de este script.

Procesamiento DOM en Python

Python provee en el módulo “xml.dom.mini-dom” una implementación sencilla de DOM. Lafunción “parse” de este modulo genera a partirde un fichero un objeto DOM. Este objeto tienetodos los métodos y atributos característicos delestándar DOM. Por ejemplo: “hasChildNodes()”,“childNodes” o “getElementsByTagName()”.Para más información sobre procesamientoDOM XML en Python se recomienda visitar lapágina http://pyxml.sourceforge.net/topics/. Ladistribución PyXML, no incluida por defecto enla distribución estándar de Python, implemen-ta un procesador de DOM más completo.El listado 3 usa el estándar DOM para procesarel fichero “Cartelera.xml” y obtener la informa-

ción correspondientea las películas encon-tradas en el mismo. Elmétodo DOM princi-pal que se utiliza es“getElementsByTagName(<nombre-ele-mento>)”, que dado elnombre de un ele-mento recupera todaslas instancias delmismo encontradas

en un árbol DOM. El atributo de un elementoDOM attributes se usa para recuperar los atri-butos de cada elemento película. Las senten-cias en la forma:

peliAttribs.getNamedItem(“codigo”).nodeValue

Permiten recuperar el contenido del atributo cuyonombre se pasa al método “getNamedItem”. Lafigura 2 muestra el resultado de tal procesamien-to. Puede verse este ejemplo en el fichero“ejemploDOM.py” incluido en el CD-ROM.

Procesamiento XSLT en Python

XSLT es un lenguaje de transformación de docu-mentos XML muy potente y complejo querequeriría para comprenderlo una serie de artí-culos por si mismo. Hay varias implementacionesXSLT en Python. Para una discusión sobre lasalternativas disponibles remitimos al lector ahttp://uche.ogbuji.net/tech/akara/nodes/2003-01-01/python-xslt. Nosotros nos hemos decan-tado por los bindings Python de las librerías XMLde Gnome libxml2 y libxlt. Versiones Windows delas mismas pueden encontrarse en http://users.skynet.be/sbi/libxml-python/. Los rpms deestas librerías para su instalación en UNIX pue-den encontrarse en http://rpmfind.net/linux/rpm2html/search.php?query=libxml2-python y http://rpmfind.net/linux/rpm2html/search.php?query=libxslt-python, respectiva-mente. El Listado 4 muestra cómo transformarun documento XML en un documento HTML pormedio de XSLT (documento “xsltexample.py” dis-ponible en el CD-ROM). Al aplicar a“Cartelera.xml” la hoja de XSLT, “Cartelera.xsl”,incluida también en el CD-ROM, se obtiene la

38

MIDDLEWARE

Figura 1. Ejecución del programa “ElementCounterSAX.py”aplicado a “Cartelera.xml”.

LISTADO 1 Documento Cartelera.xml

<?xml version=”1.0” encoding=”iso-8859-1”?><Cartelera>

<Cine codigo=’1’ nombre=’Guridi Zinemak’ direccion=’San Prudencio’ poblacion=’Vitoria-Gasteiz’>

<Pelicula codigo=’1’ titulo=’Malena’ director=’Santiago Segura’ actores=’Bo Derek, Al Pacino, Robert Reford’>

<Sesion>16:00</Sesion><Sesion>19:30</Sesion><Sesion>22:00</Sesion>

</Pelicula><Pelicula codigo=’2’ titulo=’Los Otros’

director=’Alejandro Amenabar’ actores=’Nicole Kidman’>

<Sesion>16:30</Sesion><Sesion>19:45</Sesion><Sesion>22:30</Sesion>

</Pelicula></Cine>...

</Cartelera>

LISTADO 2 Procesamiento del fichero Cartelera.xml usando SAX

# Uso: python ElementCounterSAX.py Cartelera.xmlimport sysfrom xml.sax import make_parser, handlerclass ElementCounter(handler.ContentHandler):

def __init__(self):self._elems = 0self._attrs = 0self._elem_types = {}self._attr_types = {}

def startElement(self, name, attrs):self._elems = self._elems + 1self._attrs = self._attrs + len(attrs)self._elem_types[name] = self._elem_types.get(name, 0) + 1for name in attrs.keys():

self._attr_types[name] = self._attr_types.get(name, 0) + 1def endDocument(self):

print “There were”, self._elems, “elements.”print “There were”, self._attrs, “attributes.”

print “—-ELEMENT TYPES”for pair in self._elem_types.items():

print “%20s %d” % pair

print “—-ATTRIBUTE TYPES”for pair in self._attr_types.items():

print “%20s %d” % pairparser = make_parser()parser.setContentHandler(ElementCounter())parser.parse(sys.argv[1])

Python 121.qxd 17/12/04 01:06 Página 38

Page 4: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

página web de la figura 3. El listado 5 contienesólo un pequeño fragmento de la hoja de estilo“Cartelera.xsl”. Una hoja XSLT es un documento XML bien for-mado que tiene como elemento raíz el elemento“xsl:stylesheet”. Este elemento contiene un con-junto de “xsl:templates”, o plantillas de transfor-mación que asocian un fragmento del docu-mento XML de entrada con otro del documentoXML de salida. En la especificación de XSLThttp://www.w3.org/TR/xslt, puede encontrarseuna minuciosa descripción de este lenguaje.

Programación en Jython

Jython (http://www.jython.org) es una imple-mentación Open Source en Java de Python que se

integra de manera transparente con la platafor-ma Java. Jython complementa a Java y es espe-cialmente indicada para las siguientes tareas:

Empotrar scripts en aplicaciones Java, demodo que los usuarios finales puedan escri-bir scripts que añadan funcionalidad a laaplicación. Experimentación interactiva por medio delintérprete interactivo suministrado porJython que permite interactuar con lospaquetes Java o aplicaciones en ejecución.Desarrollo rápido de aplicaciones. Los pro-gramas en Python son típicamente entre 2y 10 veces más cortos que los programasJava. Esto se traduce en una mayor produc-tividad en la programación. La integracióntransparente de Jython y Java permitecombinar estos dos lenguajes en productos.

Existen otros lenguajes de scripting que seintegran transparentemente con Java comoJacl, implementación en Java de Tcl, Rhino,implementación en Java de JavasScript oBeanShell. Sin embargo Jython se distingue deotras alternativas por:

Compilación dinámica de Jython en byte-codes de Java (conduce al mayor rendi-miento posible).Habilidad para extender las clases Java enJython.Compilación estática opcional, que permi-te la creación de applets, servlets y beans.Lo hace a través de la herramienta jythoncque transforma ficheros .PY en .CLASS.Uso del lenguaje Python que combinapoder con simplicidad sintáctica, soportan-do el modelo orientado a objetos de Java.

Las herramientas de compilación/ejecución deJython son disponibles en http://www.jython.org/download.html. Para instalarlo simple-mente hay que ejecutar el comando java jython-21, que lanzará el instalador de Jython. Comoprerrequisito, la máquina donde se instale debetener preinstalada una máquina virtual de Java. Sino se dispone de ella, puede ser obtenida desdehttp://java.sun.com/j2se/1.4.2/download.html.

Jython básicoLa figura 4 muestra una sesión interactiva deJython. Para ejecutar el intérprete de Jython

39

MIDDLEWAREPensando en Python (y IV): XML, Java e IA

Figura 2. Ejecución del programa “EjemploDOM.py” aplicado a “Cartelera.xml”.

LISTADO 4 Procesamiento del fichero Cartelera. XSLT

# Ejecuta: python xsltexample.py Cartelera.xml Cartelera.xsl Cartelera.htmlimport libxsltimport sys

if len(sys.argv) != 4:print ‘Usage: python xsltexample <xml-file> <xslt-file> <output-file>’sys.exit(0)

else:styledoc = libxml2.parseFile(sys.argv[2])style = libxslt.parseStylesheetDoc(styledoc)doc = libxml2.parseFile(sys.argv[1])result = style.applyStylesheet(doc, None)style.saveResultToFilename(sys.argv[3], result, 0)style.freeStylesheet()doc.freeDoc()result.freeDoc()

LISTADO 3 Procesamiento del fichero Cartelera.xml usando DOM

#!/usr/bin/env python# -*- coding: iso-8859-1 -*-import xml.dom.minidom, sysclass Pelicula:

def __init__(self, codigo, titulo, director, actores):self.codigo = codigoself.titulo = tituloself.director = directorself.actores = actores

def __repr__(self):return “Codigo: “ + str(self.codigo) + “ - titulo: “ + self.titulo + “ - director: “ + self.director + “ - actores: “ + self.actores

class PeliculaDOMParser:def __init__(self, filename):

self.dom = xml.dom.minidom.parse(filename)self.peliculas = []

def getPeliculas(self):# Si no hemos ya recuperado las películas en el documento ...if not self.peliculas:

peliculaNodes = self.dom.getElementsByTagName(“Pelicula”)numPelis = len(peliculaNodes)for i in range(numPelis):

pelicula = peliculaNodes.item(i)# Recuperar los attributes de cada nodo PeliculapeliAttribs = pelicula.attributescodigo = peliAttribs.getNamedItem(“codigo”).nodeValuetitulo = peliAttribs.getNamedItem(“titulo”).nodeValuedirector = peliAttribs.getNamedItem(“director”).nodeValueactores = peliAttribs.getNamedItem(“actores”).nodeValue# crear un nuevo objeto de tipo películaself.peliculas.append(Pelicula(codigo,titulo,director,actores))

return self.peliculas

if __name__ == ‘__main__’:domParser = PeliculaDOMParser(sys.argv[1])for peli in domParser.getPeliculas():

print peli

Python 121.qxd 17/12/04 01:06 Página 39

Page 5: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

simplemente hay que escribir en la línea decomando “jython”. El ejemplo muestra cómoel usuario puede crear una instancia de laclase Java “java.util.Random” para obteneruna serie de números aleatorios. Este ejem-plo ha sido “prestado” de http://www.jy-thon.org/docs/usejava. html. Como observa-mos en la figura, para crear una instancia deuna clase Java se usa la convención dePython, es decir una función con el nombrede la clase no precedida del operador “new”.En la invocación de métodos de clases Javadesde Jython hay que tener en cuenta laconversión de los tipos de datos de Python aJava, y cuando se reciben resultados loopuesto, es decir, la conversión de tipos dedatos Java en Python. Dado que Python yJava definen casi los mismos tipos de datosprimitivos, apenas hay nunca problemasdurante esta tarea de coerción (conversiónde tipos de datos).

Transformando la aplicación Tresen Raya en una aplicación Jython

Qué mejor manera de evaluar el potencial deJython que retomar nuestra conocida aplicacióndel Tres en Raya y aplicar los cambios requeridospara poderla ejecutar en Jython. Vamos a dividiresta tarea de transformación en tres fases:1.- Tres en Raya modo texto en Jython.2.- Tres en Raya modo gráfico en Jython

con acceso a mapa persistente.

3.- Tres en Raya modográfico en Jythoncon acceso a basede datos MySQL.

Tres en Raya modotexto en JythonNuestra implementaciónoriginal de Tres en Raya enmodo texto, a la que llama-mos “tresenraya.py”, re-quiere mínimos cambiospara ser ejecutable enJython. Tan solo debemosañadir dos variables globa-les “True” y “False” con losvalores 1 y 0, respectiva-mente. Esto es debido a queJython no soporta todavíael tipo booleano de Python. Hemos incluido la ver-sión modificada de este script en el CD-ROM bajoel nombre “tresenrayajython.py”. Las dos únicaslíneas que difieren del script original presentado enla primera entrega de este curso son:True = 1

False = 0

La ejecución de este script Jython se presen-ta en la figura 5.Tres en Raya modo gráfico en JythonEl siguiente paso en la transformación del juegoTres en Raya en Jython es crear la interfaz gráficadel mismo usando el paquete Swing de Java. El

listado 6 muestra el constructor de la clase“JuegoTresEnRayaJythonGUI”, incluida en el CD-ROM bajo el nombre “tresenrayajythongui.py”,junto con la implementación del método“onClick”. La lógica principal de esta aplicaciónestá gobernada por el método “jugar” no incluidopor falta de espacio pero disponible también en elCD-ROM. La clase “JuegoTresEnRayaJythonGUI”hereda de “tresenrayajython.JuegoTresEnRaya”,que es la clase base del juego. En el constructor deesta clase: (1) se obtiene una instancia a la imple-mentación de la clase del registro de jugadoresque guarda datos en un mapa persistente, (2) seinvoca al constructor de la clase base y (3) luegosimplemente se crea un “Frame” donde se colo-can los botones correspondientes a las casillas deltablero de tres en raya.Obsérvese lo sencillo que es en Jython asig-nar un manejador de eventos a un botón: button = swing.JButton(self.icono Vacio, actionPerformed=self.onClick)

Si hubiéramos efectuado una traducciónliteral del código Java a Jython hubiéramosnecesitado el siguiente código:class action(awt.event.ActionListener):

def onClick(self,event):# la implementación del manejador

button = swing.JButton(self.iconoVacio)button.addActionListener(action())

Tres en Raya modo gráfico con acceso aBD en JythonEl tercer y último ejercicio de transformación quehemos realizado ha sido convertir la clase“RegistroJugadoresDB” que vimos en la terceraentrega a Jython. En esta ocasión no usamos la

40

MIDDLEWARE

Figura 3. Página web resultante de aplicar “Cartelera.xsl” a“Cartelera.xml”.

LISTADO 5 Fragmento hoja de estilo Cartelera.xsl

<?xml version=”1.0” encoding=”iso-8859-1”?><xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform version=”1.0”>

<xsl:output method=”html”/><xsl:template match=”/”>

<html><head>

<style type=”text/css”>table {font-family: arial, ‘sans serif’; margin-left: 15pt;}th,td {font-size: 80%;}th {background-color:#FAEBD7}

</style></head><body>

<table border=”1”><xsl:apply-templates/>

</table></body>

</html></xsl:template><xsl:template match=”Cartelera”>

<xsl:for-each select=”Cine”><tr>

<th><xsl:text>Cine</xsl:text></th><th><xsl:text>Dirección</xsl:text></th><th><xsl:text>Población</xsl:text></th><th></th>

</tr>...

</xsl:stylesheet>

Python 121.qxd 17/12/04 01:06 Página 40

Page 6: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

DB API de Python, si no que JDBC para acceder ala base de datos que creamos en la tercera entre-ga. El script SQL de creación de la base de datos“tresenraya” ha sido incluido en el CD-ROMjunto con las instrucciones de cómo ejecutar estescript en MySQL. El listado 7 muestra un frag-mento de la clase transformada a la que hemosdenominado “RegistroJugadores” “DBJython”.Como las otras variedades de registros de juga-dores que hemos implementado deriva de laclase base “RegistroJugadores”. Si se desconoce lamanera de interactuar con JDBC se recomiendaal lector que repase los contenidos de los núme-ros 105, 106 y 107 de Sólo Programadores y/oque visite la página http://java.sun.com/pro-ducts/jdbc/. En pocas palabras, en el constructorde esta clase se carga el driver JDBC para MySQL(disponible en http://www.mysql.com/products/connector/j/) en memoria, se obtiene una cone-xión a la base de datos “tresenraya” y luego seutiliza esa conexión para ejecutar comandos

(Statements) SQL. Las figu-ras 6 y 7 corresponden apantallazos de la versiónJython del juego Tres enRaya en modo gráfico.

IronPython: Pythonpara .NET

En Marzo del 2004 en laconferencia PyCon fue pre-sentado IronPython (http://ironpython.com/), una implementación Pythonorientada a las plataformas .NET y Mono. Lascaracterísticas principales de IronPython son:

Tan rápida como la versión estándar dePython.Integrada de modo transparente con laCommon Language Runtime de .NET. DesdeIronPython podemos usar las librerías declases .NET y extender otras clases .NET.

Dinámico, soporta el modo de ejecucióninteractivo como Python.Opcionalmente estático, se pueden com-pilar ficheros Python para producir ejecu-tables (.EXE) que pueden ejecutarse direc-tamente o incluso DLLs. Soporta código gestionado (managed code).No finalizado, todavía en versión alfa nopuede ser utilizada para producción desoftware.

En definitiva, IronPython parece una contri-bución prometedora que nos permitirá pro-gramar aplicaciones .NET desde la cómoda ysencilla sintaxis de Python. Manténgaseatento a los progresos en este proyecto.

El algoritmo MiniMax

No quería concluir esta serie sobre Python, en laque el juego Tres en Raya nos ha ayudado aentender tantos conceptos, sin proponer un algo-ritmo más sofisticado referente a la elección decasillas por la máquina. En definitiva, muchos devosotros os habréis preguntado cómo hacer quela máquina piense y elija la mejor casilla en cadamomento. Este razonamiento es posible a travésdel algoritmo de inteligencia artificial, MiniMax.

41

MIDDLEWAREPensado en Python (y IV): XML, Java e IA

Figura 4. Sesión interactiva de Jython.

Figura 5. Sesión interactiva de “tresenrayajython.py”.

LISTADO 6 Clase JuegoTresEnRayaJythonGUI

import javafrom java import awtfrom javax import swingfrom javax.swing import JOptionPane ...class JuegoTresEnRayaJythonGUI(tresenrayajython.JuegoTresEnRaya):

def __init__(self):registro = tresenrayajython.RegistroJugadoresPersistente()tresenrayajython.JuegoTresEnRaya.__init__(self, registro, ‘solop’, ‘solop’)self.frame = swing.JFrame(‘Juego Tres en Raya’,

visible=1, windowClosing=self.exit)gridSizer = awt.GridLayout(3,3)self.frame.getContentPane().setLayout(gridSizer)self.iconoMaquina = swing.ImageIcon(‘Images\\x.PNG’)self.iconoUsuario = swing.ImageIcon(‘Images\\o.PNG’)self.iconoVacio = swing.ImageIcon(‘Images\\blank.PNG’)self.buttons = []for i in range(9):

button = swing.JButton(self.iconoVacio, actionPerformed=self.onClick)button.setBackground(awt.Color.WHITE)self.frame.contentPane.add(button)self.buttons.append(button)

self.frame.pack()...

def onClick(self, event):indexButtonClicked = self.__get_index_button_clicked(event.getSource())if self.buttons[indexButtonClicked].getIcon() == self.iconoVacio:

if not self.__jugar(indexButtonClicked):self.resetGame()self.__resetTablero()

... Figura 6. Jugando al Tres en Raya con laversión Jython.

Python 121.qxd 17/12/04 01:06 Página 41

Page 7: Pensando en Python (y IV): XML, Java e IA Pensando en Python (y

SOLO PROGRAMADORES nº 121

Antes de explicar el algoritmo es necesariauna breve introducción a árboles de búsque-da. Un árbol de búsqueda es una notaciónpara representar búsquedas. La figura 8representa uno de estos árboles. Los cuadra-dos son conocidos como nodos y represen-tan puntos de decisión en la búsqueda. Losnodos están conectados por ramas. La bús-queda comienza en el nodo raíz, en la partesuperior de la figura. En cada punto de deci-sión, los nodos para cada posible camino debúsqueda son generados, hasta que más

decisiones no sean posibles. Los nodos alfinal de la búsqueda son los nodos raíz. El algoritmo MiniMax considera la existenciade dos jugadores, el MAX y el MIN. Un árbolde búsqueda es generado, depth-first,comenzando con la posición actual del juegohasta la posición final del juego. Luego, laposición final es evaluada desde el punto devista de MAX. A continuación, los nodos inte-riores del árbol son rellenados de abajo a arri-ba con los valores evaluados. Los nodos quecorresponden al jugador MAX reciben el

máximo valor de sus hijos. Los nodos deljugador MIN el mínimo de sus hijos. Los valo-res representan cómo de bueno es el movi-miento. El jugador MAX tratará de elegir elmovimiento que maximice el valor al final.Sin embargo, el jugador MIN, mientras tanto,seleccionará los movimientos que son mejo-res para él, minimizando en todo lo posible elresultado de MAX. Para más detalles sobre este algoritmo y otrosbasados en IA recomendamos permanecer aten-tos a las novedades que incluirá SóloProgramadores en los próximos meses. En el CD-ROM ofrecemos una implementación de la apli-cación de Tres en Raya que hace uso de MiniMax.

Conclusiones

Aquí acabamos nuestro recorrido por el len-guaje de programación Python. Confío que alo largo de estas cuatro entregas el lector hayapodido descubrir el potencial de este gran len-guaje de scripting que combina a la vez poten-cia y sencillez. La aplicación de tres en rayaque hemos ido desarrollando tan solo ha mos-trado cómo implementar en Python la funcio-nalidad correspondiente a las tareas progra-máticas más típicas: programación gráfica, deacceso a bases de datos, web y XML. Por faltade tiempo no hemos podido descubrir otrasmuchas áreas en las que Python tambiénjuega un papel destacado. Espero que, tras lodescrito en esta serie, el “poder de Python” osacompañe en vuestras próximas tareas deprogramación.

42

MIDDLEWARE

Figura 7. Versión Jython de la pantalla deestadísticas.

Figura 8. Ejemplo de árbol de búsqueda.

LISTADO 7 Clase RegistroJugadoresDBJython.py

from java import langfrom java import sqlimport tresenrayajython, string, sys

class RegistroJugadoresDBJython(tresenrayajython.RegistroJugadores):def __init__(self):

tresenrayajython.RegistroJugadores.__init__(self)try:

lang.Class.forName(“org.gjt.mm.mysql.Driver”)except Exception, e:

print “Se ha producido un error en la carga del driver”, e

try:url = “jdbc:mysql://localhost:3306/tresenraya”self.con = sql.DriverManager.getConnection(url,”tresenraya”,”tresenraya”)

except Exception, e:print “Se ha producido un error en el establecimiento de la

conexion con la base de datos”, e

# Asegurarse que si no existe un usuario solop se añadausuarioSolop = self._executeSQLCommand(“select * from usuario where

nombreUsuario=’solop’”)...

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

try:stmt = self.con.createStatement()if string.lower(command).startswith(‘select’): # si es una select ...

rs = stmt.executeQuery(command)metadata = rs.getMetaData()# recupera todas las filaswhile rs.next():

# recupera todas las columnascontenidoFila = []for i in range(1, metadata.getColumnCount()+1):

try:columnType = metadata.getColumnType(i)contenidoColumna = Noneif columnType == sql.Types.INTEGER:

contenidoColumna = rs.getInt(i)elif columnType == sql.Types.VARCHAR:

contenidoColumna = rs.getString(i)else:

contenidoColumna = rs.getObject(i)contenidoFila.append(contenidoColumna)

except Exception, e:print ebreak

resultado.append(tuple(contenidoFila))else:

stmt.execute(command)except:

raise u’Excepcion producida en ejecucion de comando’ + commandreturn resultado

Python 121.qxd 17/12/04 01:06 Página 42