martes, enero 30, 2007
Tipos set y Set
Me acabo de dar cuenta de que a partir de la versión 2.4 de python existe como 'built-in type' el tipo set.
En versiones anteriores había que usar el tipo Set del modulo sets.
Por lo que he podido leer es mas mejor ahora usar set.
En versiones anteriores había que usar el tipo Set del modulo sets.
Por lo que he podido leer es mas mejor ahora usar set.
Un post interesante de OjoBuscador de José R. Pérez Agüera: Todo el mundo tiene un buscador, pero ¿realmente lo tienen? Interesante echarle un ojo a los comentarios.
lunes, enero 29, 2007
Ejecutar comandos del sistema
Conocía os.system, pero hoy en la python-es han comentado un par de opciones mas; popen:
import os
data=os.popen('ls').read()
file=open('fichero.txt','w')
file.write(data)
file.close()
Y con commands:
import commands
out = commands.getoutput('ls')
f = file('lsout.txt', 'w')
f.write(out)
f.close()
import os
data=os.popen('ls').read()
file=open('fichero.txt','w')
file.write(data)
file.close()
Y con commands:
import commands
out = commands.getoutput('ls')
f = file('lsout.txt', 'w')
f.write(out)
f.close()
viernes, enero 26, 2007
Mas sobre cssutils
Antes de nada indicar que estoy usando la distribución 0.9.1b3 de cssutils.
Tests
En teoria los test podriamos ejecutarlos tras hacer una build del paquete, o incluso tras descomprimirlo. Mediante:
python setup.py test
Pero por lo que sea no me ha funcinado. Bueno no pasa nada... podemos lanzar los test desde el directorio de tests (../src/cssutils/tests) de la siguiente manera (en 'kk' tendremos la salida):
for i in test_*.py; do echo $i >> kk; python $i >> kk 2>&1; done
Veremos que aparecen trazas de error. No pasa nada. Lo importante es que el test nos devuelva OK.
encutils
cssutils tiene un paquete, encutils, a tener en cuenta.
La funcion principal es getEncodingInfo que devuelve informacion sobre le encoding. Esta informacion se extrae del elemento pasado: headers de HTTPResponse, XML declaration y lementos meta X/HTML.
Resumiendo podemos pasar un HTTPResponse o un texto como argumento.
Aunque no la he probado, parece currada.
csscapture
Permite extraer todos las hojas de estilo de una url determinada (incluyendo las que estan embebidas en la propia página html).
Usa HTMLParser.
El parseo (interioridades)
El parser desencadena el parseo al asignar el texto del css al objeto CSSStylesheet.
Para realizar el parseo se usa tokenizer.CSSTokenizer.
El único pero que veo a cssutils es que es un poco lento con el parseo. Necesitamos mas velocidad. No se si se podrá obtimizar algo... He estado echando un vistazo rápido pero el codigo no es sencillo.
Habrá que meteler el profiler, a ver si hay algo que canta.
Tests
En teoria los test podriamos ejecutarlos tras hacer una build del paquete, o incluso tras descomprimirlo. Mediante:
python setup.py test
Pero por lo que sea no me ha funcinado. Bueno no pasa nada... podemos lanzar los test desde el directorio de tests (../src/cssutils/tests) de la siguiente manera (en 'kk' tendremos la salida):
for i in test_*.py; do echo $i >> kk; python $i >> kk 2>&1; done
Veremos que aparecen trazas de error. No pasa nada. Lo importante es que el test nos devuelva OK.
encutils
cssutils tiene un paquete, encutils, a tener en cuenta.
La funcion principal es getEncodingInfo que devuelve informacion sobre le encoding. Esta informacion se extrae del elemento pasado: headers de HTTPResponse, XML declaration y lementos meta X/HTML.
Resumiendo podemos pasar un HTTPResponse o un texto como argumento.
Aunque no la he probado, parece currada.
csscapture
Permite extraer todos las hojas de estilo de una url determinada (incluyendo las que estan embebidas en la propia página html).
Usa HTMLParser.
El parseo (interioridades)
El parser desencadena el parseo al asignar el texto del css al objeto CSSStylesheet.
Para realizar el parseo se usa tokenizer.CSSTokenizer.
El único pero que veo a cssutils es que es un poco lento con el parseo. Necesitamos mas velocidad. No se si se podrá obtimizar algo... He estado echando un vistazo rápido pero el codigo no es sencillo.
Habrá que meteler el profiler, a ver si hay algo que canta.
martes, enero 23, 2007
Python bindings
Un par de productos para crear bindings entre python y otros lenguajes:
- boost.python. Para C++
- swig. [introducción]
lunes, enero 22, 2007
Parsers de CSS
He tenido que mirar que hay por ahí, para parsear CSS's en python. Lo primero que tengo que decir es que estoy realmente sorprendido. No he encontrado ningún producto maduro, y ni siquiera unos bindings en python.
Los dos parsers que he encontrado en python usan además DOM, por lo que no hay nada SAX (o en gerga CSS SAC).
Esto significa que alguien con interés, ganas y tiempo puede hacer algo útil para la comunidad del software libre...
Pero lo que mas me sorprende es no haber encontrado nada ni en python-es, ni en comp.lang.python.
Antes de entrar a comentar los parsers, comentar que CSS tiene tres versiones, CSS1, CSS2 y CSS3 (en desarrollo).
Todos los parsers implementan CSS1 y por lo que he podido ver CSS2 parcialmente.
Bueno al lio... los parsers de python encontrados son:
Si no nos convencen ninguno de los dos, no nos va a quedar mas remedio que implementar unos bindings a alguno existente en C (vamos lo normal en python... no lo vamos a hacer de uno implementado en Java; ummm, aunque no he dicho un disparate... siempre se puede usar jython ;)). En C he encontrado:
Finalmente se puede intentar usar el parser que use algún browser (implementando el binding correspondiente, claro). Entre los disponibles parece que el candidato más lógico sería usar del del firefox, Gecko.
Mas info sobre el parser de CSS de Gecko aquí.
Los dos parsers que he encontrado en python usan además DOM, por lo que no hay nada SAX (o en gerga CSS SAC).
Esto significa que alguien con interés, ganas y tiempo puede hacer algo útil para la comunidad del software libre...
Pero lo que mas me sorprende es no haber encontrado nada ni en python-es, ni en comp.lang.python.
Antes de entrar a comentar los parsers, comentar que CSS tiene tres versiones, CSS1, CSS2 y CSS3 (en desarrollo).
Todos los parsers implementan CSS1 y por lo que he podido ver CSS2 parcialmente.
Bueno al lio... los parsers de python encontrados son:
- cssutils (beta) y
- TechGame Framework CSS Parser and Engine (alpha)
Si no nos convencen ninguno de los dos, no nos va a quedar mas remedio que implementar unos bindings a alguno existente en C (vamos lo normal en python... no lo vamos a hacer de uno implementado en Java; ummm, aunque no he dicho un disparate... siempre se puede usar jython ;)). En C he encontrado:
- El SAC de w3.org.
- Libcroco: parser SAC y CSSOM like api para gnome.
Finalmente se puede intentar usar el parser que use algún browser (implementando el binding correspondiente, claro). Entre los disponibles parece que el candidato más lógico sería usar del del firefox, Gecko.
Mas info sobre el parser de CSS de Gecko aquí.
jueves, enero 11, 2007
Validad un DTD
Si queremos validar un DTD lo que podemos hacer es usar un validador de xml que use dicho DTD.
Al cargarlo detectará posibles errores.
Por ejemplo podemo susar xmllint:
xmllint --valid
Al cargarlo detectará posibles errores.
Por ejemplo podemo susar xmllint:
xmllint --valid
miércoles, enero 10, 2007
RSS Readers
Ya he comentado anteriormente sobre agregadores de feeds: [1],[2] y [3].
Me vuelve a surgir el tema porque tengo que obtener feeds de una intranet, por lo que los lectores web no me sirven. Voy a tener que usar el firefox o bien una aplicación local.
Para windows me recomiendan Omea Reader (Net 2.0) y para linux liferea (gnome) o kagregator. (kde)
Con el firefox voy a echarle un vistazo a sage y ver como funcionan los live bookmarks.
Me vuelve a surgir el tema porque tengo que obtener feeds de una intranet, por lo que los lectores web no me sirven. Voy a tener que usar el firefox o bien una aplicación local.
Para windows me recomiendan Omea Reader (Net 2.0) y para linux liferea (gnome) o kagregator. (kde)
Con el firefox voy a echarle un vistazo a sage y ver como funcionan los live bookmarks.
martes, enero 09, 2007
¿libxml2 leak in python (html sax-parsing)?
Me siento un poco fustrado con el parser de html de libxml2. Se nos va memoria a saco y no tengo ni idea de como evitarlo.
He preguntado a la lista, pero no ha servido de mucho. A ver si me aclaran algo mas... Actualizaré el post cuando sepa algo.
Tras detectar que en nuestro codigo el mayor problema con la memoria lo teníamos con el parser sax de html de libxml2, modifiqué el test que acompaña a la distribución (pushSAXhtml.py)para que en lugar de procesar 1 fichero, procese N, siendo N un número suficientemente grande para ver las perdidas de memoria...
Pues bien, en algo mas de 10 minutos procesando el proceso se cae por un segmentation fault.
El específico en el bucle para procesar el fichero por el parser es:
ctxt = libxml2.htmlCreatePushParser(handler, initdata, 0, inputFilePath)
ctxt.htmlParseChunk(data, len(data), 1)
ctxt = None
En el callback no hacemos nada:
class callback:
def startDocument(self):
print "."
def endDocument(self):
pass
def startElement(self, tag, attrs):
pass
def endElement(self, tag):
pass
def characters(self, data):
pass
def warning(self, msg):
pass
def error(self, msg):
pass
def fatalError(self, msg):
pass
¡Ojo! la fuga de memoria la vemos a nivel del sistema operativo (con top o mirando en /proc (por ejemplo con mem-monitor)), ya que las rutinas específicas de libxml2 nos indican que todo está OK.
En fin... que con este problema no podemos llevar nuestro codigo a producción. O solucionamos esto o tenemos que mirar otro parser (posible candidato beautifulsoup); cosa que no me gustaría.
Otra cosa que me ha frustado mucho es no encontrar nada en la web. ¿Es que nadie por ahí esta parseando html con libxml2 usando SAX? No me lo puedo creer...
Ah! un detalle que se me olvidada. En el código asignamos None al contexto. Es correcto. Eso provoca la invocación a xmlFreeParserCtxt(que es lo mismo que htmlFreeParserCtxt: esta llama a la anterior). Con lo cual no tenemos que liberar nada mas, ya que el documento no lo usamos. De hecho si intentamos obtener el documento los bindings de python nos devolverán una excepción.
Para terminar de cerrar el tema y asegurame de que no hay nada raro en mi entorno he hecho el ejemplo equivalente en C, y ha funcionado sin problemas. Ahí va el codigo:
Para hacerlo operativo modificar las constantes BUFFER_SIZE, NUM_ITERS, FILE_PATH, al gusto del consumidor.
He preguntado a la lista, pero no ha servido de mucho. A ver si me aclaran algo mas... Actualizaré el post cuando sepa algo.
Tras detectar que en nuestro codigo el mayor problema con la memoria lo teníamos con el parser sax de html de libxml2, modifiqué el test que acompaña a la distribución (pushSAXhtml.py)para que en lugar de procesar 1 fichero, procese N, siendo N un número suficientemente grande para ver las perdidas de memoria...
Pues bien, en algo mas de 10 minutos procesando el proceso se cae por un segmentation fault.
El específico en el bucle para procesar el fichero por el parser es:
ctxt = libxml2.htmlCreatePushParser(handler, initdata, 0, inputFilePath)
ctxt.htmlParseChunk(data, len(data), 1)
ctxt = None
En el callback no hacemos nada:
class callback:
def startDocument(self):
print "."
def endDocument(self):
pass
def startElement(self, tag, attrs):
pass
def endElement(self, tag):
pass
def characters(self, data):
pass
def warning(self, msg):
pass
def error(self, msg):
pass
def fatalError(self, msg):
pass
¡Ojo! la fuga de memoria la vemos a nivel del sistema operativo (con top o mirando en /proc (por ejemplo con mem-monitor)), ya que las rutinas específicas de libxml2 nos indican que todo está OK.
En fin... que con este problema no podemos llevar nuestro codigo a producción. O solucionamos esto o tenemos que mirar otro parser (posible candidato beautifulsoup); cosa que no me gustaría.
Otra cosa que me ha frustado mucho es no encontrar nada en la web. ¿Es que nadie por ahí esta parseando html con libxml2 usando SAX? No me lo puedo creer...
Ah! un detalle que se me olvidada. En el código asignamos None al contexto. Es correcto. Eso provoca la invocación a xmlFreeParserCtxt(que es lo mismo que htmlFreeParserCtxt: esta llama a la anterior). Con lo cual no tenemos que liberar nada mas, ya que el documento no lo usamos. De hecho si intentamos obtener el documento los bindings de python nos devolverán una excepción.
Para terminar de cerrar el tema y asegurame de que no hay nada raro en mi entorno he hecho el ejemplo equivalente en C, y ha funcionado sin problemas. Ahí va el codigo:
/* libxml2 C HTML Parser Example
* gcc-I -L -lxml2
*/
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 100000
#define NUM_ITERS 10000
#define FILE_PATH ""
/*****************************************************************************/
/*
* Foo context structure
*/
typedef struct
{
int foo;
} Context;
/*
* libxml start element callback function
*/
void startElement(void *voidContext,
const xmlChar *name,
const xmlChar **attributes)
{
return;
}
/*
* libxml end element callback function
*/
void endElement(void *voidContext,
const xmlChar *name)
{
return;
}
/*
* Text handling helper function
*/
void handleCharacters(Context *context,
const xmlChar *chars,
int length)
{
return;
}
/*
* libxml PCDATA callback function
*/
void characters(void *voidContext,
const xmlChar *chars,
int length)
{
return;
}
/*
* libxml CDATA callback function
*/
void cdata(void *voidContext,
const xmlChar *chars,
int length)
{
return;
}
htmlSAXHandler saxHandler =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
startElement,
endElement,
NULL,
characters,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
cdata,
NULL
};
/*****************************************************************************/
char buffer[BUFFER_SIZE];
int main(void)
{
htmlParserCtxtPtr ctxt;
Context context;
char *filepath=FILE_PATH;
FILE *f = NULL;
long fileLen = 0;
long retRead = 0;
int i=0;
/*---- Reading the data */
/*
struct stat myStat;
stat(filepath,&myStat);
if (myStat.st_size >= BUFFER_SIZE)
{
print("El fichero no cabe en el buffer\n");
return 1;
}
*/
f = fopen(filepath, "r");
if ( f == NULL ) /* Could not open file */
{
printf("Error opening %s: %s (%u)\n", filepath, strerror(errno), errno);
return 1;
}
fseek(f, 0L, SEEK_END); /* Position to end of file */
fileLen = ftell(f); /* Get file length */
rewind(f); /* Back to start of file */
if (fileLen >= BUFFER_SIZE)
{
printf("El fichero no cabe en el buffer: %d\n",fileLen);
return 1;
}
retRead = fread(buffer,fileLen,1,f);
if (retRead != 1)
{
printf("Error haciendo el read");
return 1;
}
fclose(f);
/*---- We parser the file */
for(i=0;i < NUM_ITERS; ++i)
{
ctxt = htmlCreatePushParserCtxt(&saxHandler, &context, "", 0, "",
XML_CHAR_ENCODING_NONE);
htmlParseChunk(ctxt, buffer, fileLen, 0);
htmlParseChunk(ctxt, "", 0, 1);
htmlFreeParserCtxt(ctxt);
printf(".\n");
}
return 0;
}
Para hacerlo operativo modificar las constantes BUFFER_SIZE, NUM_ITERS, FILE_PATH, al gusto del consumidor.
miércoles, enero 03, 2007
Uso de etiquetas en blogger
Hace poco he migrado todos mis blogs a la nueva versión de blogger. Mi mayor interés para ello era el poder etiquetar los posts.
Pero una vez hecho, la template usada se mantenía (no se mostraban las labels). Tras estar indagando un poco he visto que es necesario actualizar la template, pudiendo modificar el diseño a golpe de ratón, cosa que antes no se podía. Es una gran mejora.
¡¡¡Ojo!!! Si en la template anterior habeis hecho modificaciones a mano se perderán, si no las meteis en la nueva template antes de guardarla.
Ya con respecto a las etiquetas indicar un par de cosas:
Y ya para acabar indicar que si estamos en blogger, cuando estamos visualizando nuestro blog, nos permite editar los elementos compositivos de la template (por ejemplo añadir un enlace a la lista de enlaces).
Resumiendo: ha mejorado mucho blogger con esta nueva versión.
Pero una vez hecho, la template usada se mantenía (no se mostraban las labels). Tras estar indagando un poco he visto que es necesario actualizar la template, pudiendo modificar el diseño a golpe de ratón, cosa que antes no se podía. Es una gran mejora.
¡¡¡Ojo!!! Si en la template anterior habeis hecho modificaciones a mano se perderán, si no las meteis en la nueva template antes de guardarla.
Ya con respecto a las etiquetas indicar un par de cosas:
- se muestran como una lista, bien ordenada alfabéticamente o por frecuencia
- se pueden hacer feeds por las etiquetas; mas información aquí.
Y ya para acabar indicar que si estamos en blogger, cuando estamos visualizando nuestro blog, nos permite editar los elementos compositivos de la template (por ejemplo añadir un enlace a la lista de enlaces).
Resumiendo: ha mejorado mucho blogger con esta nueva versión.
martes, enero 02, 2007
Suscribirse a:
Comentarios (Atom)