Antes de nada comentar que no lo he probado, pero me gustaría...
Se puede usar webkit desde python a bravés de pywebkitgtk.
Relacionadas, parte de pywebkitgtk, veo que también existen Pyjamas and python-qt4-webkit.
Intentando investigar un poquito sobre este tema... que he encontrado este post de comp.lang.pyhon (enfocado principalmente a ejecutar javascript, pero relacionado):
"pyv8 is the newest addition: http://advogato.org/article/985.html
it's a python wrapper around google's v8 javascript execution
library.
then there's pykhtml: http://paul.giannaros.org/pykhtml/
it's a python wrapper around KHTML, providing very convenient access
to KDE's HTML capabilities: what pykhtml does is "pretends" that the
GUI part of KDE doesn't exist, so you can run your program as a
command-line shell; it will execute the javascript, which you will
have to wait a bit for of course; then you can walk the DOM tree
(using pykhtml bindings) using pykhtml.DOM.getElementById() and
getElementsByTagName("a") etc. etc. looking for the URLs.
there's even an AJAX example included which does 1-second polling of
the DOM model, waiting for a spell-checking web site to deliver the
answer.
then there's webkit, with the new glib bindings:
https://bugs.webkit.org/show_bug.cgi?id=16401
which are then followed up by python bindings to _those_ bindings:
http://code.google.com/p/pywebkitgtk/issues/detail?id=13
this will also allow you to execute arbitrary javascript - again, it's
similar to KHTML and in fact webkit really _is_ the KDE KHTML code
(JavaScriptCore, KJS etc) but forked, improved, etc. etc.
unfortunately, the glib bindings are tied - at three key and strategic
locations - to gtk at the moment, which will take _very_ little work
to "un"tie them [pay me and i'll do the work], so you would need to
create a blank gtk window - just like is done with pykhtml, behind the
scenes.
it would be a very simple task to create a "dummy" - console-based -
port of webkit, providing an array of callbacks which you must hand to
the library. at the moment, the design of webkit is not particularly
good in this respect: there are three ports, gtk, wx and qt, which are
heavily tied in to webkit. it would be a _far_ better design to be
passing in a struct containing function callbacks (rather a lot of
them - about eighty!) and then what you could do is have a "console"-
based port of webkit, which would do the job you needed.
alternatively, if you don't mind wrapping a binary application with
e.g. Popen3 then look at the webkit DumpRenderTree application, paying
particular attention to using the --html option. you won't have any
control over how long the javascript is executed for. after an
arbitrary and small period of time, DumpRenderTree _stops_ executing
the javascript and prints out the HTML DOM model (in a non-html-layout
fashion - it's used for debugging and testing purposes but will
suffice for your purposes).
so, as it stands, pywebkitgtk is _no worse_ than pykhtml, but with a
little bit of tweaking, the "gtk" could be removed from "pywebkitgtk"
and you'd end up with... ohh... call it "pywebkitglib" ... which would
be much better as a stand-alone library, for your purposes
then there's also "spidermonkey", which is mozilla's javascript
engine. i haven't investigated this option: haven't had a need to.
then there's also PyXPCOMExt, which is embedding python into mozilla,
and from there you have PyDOM, which allows you access to the DOM
model of the mozilla "thing". so, if you don't mind embedding your
application into XULRunner, you've got a home for executing your app
and obtaining the urls, post-javascript-execution.
the neat thing about PyXPCOMExt is that you have complete and full
access to python - so your app can make external TCP and UDP sockets,
you can embed an entire _server_ in the damn thing if you want (you
could embed... python-twisted if you wanted!) you can access the
filesystem - anything. absolutely anything. reason: the _entire_
python suite is embedded into the browser. every single bit of it.
that's about all i've been able to find, so far. there might be more
options out there. not that there aren't enough already :)
all of them will allow you complete and full access to execution of
javascript, including AJAX execution. which is why you'll need to do
that "polling" trick in many instances. "
miércoles, octubre 22, 2008
lunes, octubre 20, 2008
Pasar de pdf a texto/html
Para extraer el texto del pdf, se de dos aplicaciones que funcionan bien:
Por lo visto en una etapa del pipeline de fast (de las que vienen disponibles), se usa xpf (no lo puedo asegurar al 100%).
Nosotros en cierta ocasión usabamos el segundo (¿o fue pdf2html?). Porque nos daba mejores resultados.
Si quieres hilar mas fino, y no depender de una aplicación externa existe Poppler.
Parece que ha habido un amago de hacer bindings a python para poppler...
Uno de los peor de poppler es que no hay documentación.
Dentro del paquete poppler-utils, hay utilidades de conversión.
He visto que existe el paquete pyPdf.
Por lo visto en una etapa del pipeline de fast (de las que vienen disponibles), se usa xpf (no lo puedo asegurar al 100%).
Nosotros en cierta ocasión usabamos el segundo (¿o fue pdf2html?). Porque nos daba mejores resultados.
Si quieres hilar mas fino, y no depender de una aplicación externa existe Poppler.
Parece que ha habido un amago de hacer bindings a python para poppler...
Uno de los peor de poppler es que no hay documentación.
Dentro del paquete poppler-utils, hay utilidades de conversión.
He visto que existe el paquete pyPdf.
viernes, octubre 17, 2008
Primer curso python impartido

Bueno... ayer se acabó el primer curso python.
No se como habrá resultado, ya que es dificil verse desde fuera (estaría genial poderse ver grabado, para corregir posibles defectos). Pero creo que en general ha estado bien.
Aparte de mi exposición, el material desde luego si que creo que está bastante bien.
Tras la experiencia del curso, quizás podría retocar alguna cosa (muy poca), o por mi parte mirar con mas detalle alguna referencia. Pero la verdad... para un curso de 12 horas, poco mas puedo ampliar. El tiempo está muy bien ajustado ya.
Lo malo, pero esto ya es típico de los cursos dentro de una empresa, quizas un poco de falta de interés por algun alumno (bueno es la percepción desde el lado del profesor). Pero vamos.... esto es algo de esperar. Pero con que haya ya sólo uno con interés es suficiente. Aún así, la gente con menos interés ha podido ver de que va esto de python...
El peor día fue el primero, en el que empecé con un poco de tensión, pero una vez superada el resto bien.
El último día me lleve un chasco. Hice una demo sobre como con joins() la concatenación de cadenas es mas eficaz que usando el operador '+'. Y no fue así. Los tiempos salieron similares.... [1]
A la presentación que tenía preparada le añadí contenido de la presentación de Gustavo Picón, para hacerla mas amena. Sobre todo para el comienzo.
El hacer un curso en python, es realmente muy sencillo, por la interactividad que te permite el interprete.
A la hora de escoger ejercicios para realizar por el alumno, hay dos opciones: hacer muchos ejercicios sencillos, o hacer menos pero mas complejos (no por la dicitultad del problema, sino por que consitas en hacer aplicaciones que realmente hagan algo).
Me decidí por la segunda opción.
En cuanto a la teoría indicar, que la aproximación al contenido ha sido la de pensar, según mi experiencia que debería tener. Y a partir de ahí elaborarlo, tirando de distintas fuentes y metiendo muchas referencias externas.
Lo mas sencillo hubiera sido fusilar algo ya existente, pero no me interesaba esta aproximación (mucho mas cómoda para mi). Ahora cualquiera con interés puede ver libros, u otras presentaciones y el contenido será diferente.
Al final el curso está dividido en 4 partes correspondientes a 4 dias (3 horas por dia):
- Teoría, jugar un poco con python
- Ejercicio 1 y explicación
- Teoría, comienzo de Ejercicio 2
- Explicación ejercicio 2, y practica libre
Ya para acabar, indicar que en la web hay muchas presentaciones (incluso videos). Ahí va un listado de presentaciones de guido.
Y el enlace a la presentación del curso: El mundo de python.
Notas:
[1] Efectivamente, hay novedades que no sabia sobre esto. Por lo visto desde CPython 2.4 según What's New in Python 2.4: "String concatenations in statements of the form s = s + "abc" and s += "abc" are now performed more efficiently in certain circumstances. This optimization won't be present in other Python implementations such as Jython, so you shouldn't rely on it; using the join() method of strings is still recommended when you want to efficiently glue a large number of strings together."
jueves, octubre 16, 2008
NTLM Authorization Proxy Server
Relacionado con el firefox, ya comenté hace tiempo de una extensión interesante. MM3-ProxySwitch. Es interesante si necesitamos cambiar frecuentemente de proxies.
Otra utilidad muy util es un script en python que te permite autentificarte ante un proxy NTLM.
Si tenemos el MS Proxy Server y no estamos en el dominio, con firefox será un infierno navegar, ya que nos pedirá que nos autentifiquemos con cada petición. Este script, NTLM Authorization Proxy Server, lo soluciona.
Su autor Dmitry Rozmanov.
He indagado en Pypi, pero no está. Eso si, me he encontrado otro proxy disponible.
Otra utilidad muy util es un script en python que te permite autentificarte ante un proxy NTLM.
Si tenemos el MS Proxy Server y no estamos en el dominio, con firefox será un infierno navegar, ya que nos pedirá que nos autentifiquemos con cada petición. Este script, NTLM Authorization Proxy Server, lo soluciona.
Su autor Dmitry Rozmanov.
He indagado en Pypi, pero no está. Eso si, me he encontrado otro proxy disponible.
domingo, septiembre 28, 2008
Singleton
Necesitaba encontrar un ejemplo sobre uso de metaclases en python, y me decanté por el patrón Singleton, ya que había visto algo.
Resumiendo... la mejor solución actual es usando metaclases y es:
No se si tiene algun problema, ya que no estoy nada puesto en metaclases. Para acabar unas referencias comentadas:
Resumiendo... la mejor solución actual es usando metaclases y es:
class Singleton(type):
def __init__(cls, name, bases, dct):
cls.__instance = None
super(Singleton,cls).__init__(cls, name, bases, dct)
def __call__(cls, *args, **kw):
if cls.__instance is None:
cls.__instance = super(Singleton,cls).__call__(cls, *args,**kw)
return cls.__instance
No se si tiene algun problema, ya que no estoy nada puesto en metaclases. Para acabar unas referencias comentadas:
- wiki-es: donde ví la implementación de metaclases. Pero el cçodigo aquçi incluido varia en que usa super.
- wiki-en: no tiene la opción de metaclass
- Gary Robinson, implementa un singleton siguiendo unas ideas de aquí. No he tenido tiempo de mirarlo. Pero lo dejo anotado, ya que puede merecer la pena echarle un ojo.
viernes, septiembre 26, 2008
Google Moderator
Leo en genbeta sobre una aplicación sobre Google App Engine, Google Moderator.
Veo que están metiendo preguntas para Guido sobre python.
Veo que están metiendo preguntas para Guido sobre python.
Python popularity
viernes, septiembre 12, 2008
Webkit vs Gecko
Hay un post en barrapunto sobre una comparativa entre WebKit y Gecko.
Me ha congratulado leer algún comentario sobre Gecko que cuadra totalmente con lo que yo ví una vez que intenté evaluar si nos podia servir para un proyecto:
El artículo (el de dosideas) está muy bien, y es corto.
Me ha congratulado leer algún comentario sobre Gecko que cuadra totalmente con lo que yo ví una vez que intenté evaluar si nos podia servir para un proyecto:
- no había documentación por ningún lado
- la organización del codigo es un cristo, no está nada modularizado, aparte que la cantidad de codigo de la base es... brutal!!!
El artículo (el de dosideas) está muy bien, y es corto.
sábado, septiembre 06, 2008
Google Chrome
La novedad de la semana... ¿Y será la última de septiembre? Seguro que no... ya que es el decimo aniversario de google.
Hay un post relacionado de dirson que también está muy bien, va sobre una encuesta sobre los productos de google.
Hay muchas cosas por leer entorno a Chrome, pero todavía no he tenido mucho tiempo...
Por de pronto comentar que el comic, está relamente bien. Redomendable su lectura.
Ya un detalle super geek. Tras instalarmelo me aparece un artículo de Ian Bicking, como en los marcadores y como los mas visitados...
Es curioso... porque en el usuario que uso habitualmente no lo tengo ni en favoritos. Tendré que revisar el usuario admin...
Hay un post relacionado de dirson que también está muy bien, va sobre una encuesta sobre los productos de google.
Hay muchas cosas por leer entorno a Chrome, pero todavía no he tenido mucho tiempo...
Por de pronto comentar que el comic, está relamente bien. Redomendable su lectura.
Ya un detalle super geek. Tras instalarmelo me aparece un artículo de Ian Bicking, como en los marcadores y como los mas visitados...
Es curioso... porque en el usuario que uso habitualmente no lo tengo ni en favoritos. Tendré que revisar el usuario admin...
sábado, agosto 30, 2008
Directorio de programación
En python.es surgió la idea de crear un directorio de blogs sobre python.
No había compartido nunca el enlace enl a lista, pero bueno... la verdad es que ya tengo unos cuantos contenidos en python que pueden ser interesantes.
El link irá a parar a directorioprogramacion.blogspot.com.
Habrá que echarle un ojo a ver como crece su contenido.. .
No había compartido nunca el enlace enl a lista, pero bueno... la verdad es que ya tengo unos cuantos contenidos en python que pueden ser interesantes.
El link irá a parar a directorioprogramacion.blogspot.com.
Habrá que echarle un ojo a ver como crece su contenido.. .
jueves, agosto 28, 2008
lxml
Ya he mentado en algun post anterior este parser de xml/html, pero no había tenido ocasión de probarlo.
En el proyecto ahora tenemos que manejar unos xml y hasta la fecha habíamos usado libxml2... Era el momento de cambiar... y la verdad es que está muy bien. Y bien documentado.
Ahí van unos enlaces:
En el proyecto ahora tenemos que manejar unos xml y hasta la fecha habíamos usado libxml2... Era el momento de cambiar... y la verdad es que está muy bien. Y bien documentado.
Ahí van unos enlaces:
jueves, agosto 21, 2008
Shutdown programado en windows
Hoy he aprendido un comando superutil:
shutdown -s -t [tiempo]
Te sirve para programar un shutdown en windows. Es muy util, imaginaros que habeis dejado descargandose algo y os quereis ir a la cama...
Con /? podeis ver el resto de opciones.
shutdown -s -t [tiempo]
Te sirve para programar un shutdown en windows. Es muy util, imaginaros que habeis dejado descargandose algo y os quereis ir a la cama...
Con /? podeis ver el resto de opciones.
HTTrack
Hacía mucho que no usaba un Web Spider (o crawler). Y aprovechando que para el proyecto estamos usado HTTrack, lo he probado para un uso personal.
La verdad... esta muy bien. El único pero que le hemos visto es que no puedes obtener un mapeo entre las direcciones web, y las locales.
Se puede usar tanto para Linux, como para Windows.
Y ya lo que me ha sorprendido es que hay disponible una librería python, para usarlo desde python: httrack-py.
En linux, recordar que podemos usar para para los mismo wget.
En la wikipedia, podeis encontrar muchos mas crawlers.
La verdad... esta muy bien. El único pero que le hemos visto es que no puedes obtener un mapeo entre las direcciones web, y las locales.
Se puede usar tanto para Linux, como para Windows.
Y ya lo que me ha sorprendido es que hay disponible una librería python, para usarlo desde python: httrack-py.
En linux, recordar que podemos usar para para los mismo wget.
En la wikipedia, podeis encontrar muchos mas crawlers.
martes, agosto 19, 2008
ConfigParser
Modulo muy útil para manejar ficheros de configuración en formato clave/valor y con secciones.
Vamos... al estilo de los .ini de windows.
Dentro del módulo se definen 3 clases:
Yo hasta la fecha había usado ConfigParser, pero se te puede quedar corta...
El comportamiento de los métodos get() es que si una clave no existe te da una Excepción.
Nosotros hemos ampliado el interfaz con una variante de los métodos para que si una clave no existe, te devuelva el valor que le pasas por defecto. Vamos... similar que lo que puedes hacer desde el constructor, pero a nivel de método.
Lo que si que soporta son 'interpolaciones'. Es decir, el poder usar valores de variables como valores de otras variables dentro del mismo fichero de configuración.
Otra ampliación que le hemos metido es el poder hacer sustituciones en los valores a partir de variables del entorno. Para esto usamos el formato ${varname}. La verdad... Se podría haber hecho con las interpolaciones, usando el argumento opcional 'vars'.
SafeConfigParser simplemente modifica el método ser() para garantizar que el valor pasado sea un string.
Vamos... al estilo de los .ini de windows.
Dentro del módulo se definen 3 clases:
- RawConfigParser
- ConfigParser
- SaveConfigParser
Yo hasta la fecha había usado ConfigParser, pero se te puede quedar corta...
El comportamiento de los métodos get() es que si una clave no existe te da una Excepción.
Nosotros hemos ampliado el interfaz con una variante de los métodos para que si una clave no existe, te devuelva el valor que le pasas por defecto. Vamos... similar que lo que puedes hacer desde el constructor, pero a nivel de método.
Lo que si que soporta son 'interpolaciones'. Es decir, el poder usar valores de variables como valores de otras variables dentro del mismo fichero de configuración.
Otra ampliación que le hemos metido es el poder hacer sustituciones en los valores a partir de variables del entorno. Para esto usamos el formato ${varname}. La verdad... Se podría haber hecho con las interpolaciones, usando el argumento opcional 'vars'.
SafeConfigParser simplemente modifica el método ser() para garantizar que el valor pasado sea un string.
jueves, agosto 14, 2008
Chuletilla para subversion
Estaba ya usando desde hacía tiempo subversion, pero la verdad... tampoco había leido demasiado sobre el mismo...
He ido tirando con mis conocimientos (básicos) sobre CVS. Pero notaba mis carestías, por lo que me dispuse a leer los capítulos 1,2 y 3 del siguiente libro. Se lo recomiendo a cualquier que esté trabajando con subversión; o que vaya a trabajar... Se lee rápido.
A continuación una chuletilla de cosas extraidas del susodicho..
Una vez hecho el checkout, el ciclo de trabajo típico es como sigue:
He ido tirando con mis conocimientos (básicos) sobre CVS. Pero notaba mis carestías, por lo que me dispuse a leer los capítulos 1,2 y 3 del siguiente libro. Se lo recomiendo a cualquier que esté trabajando con subversión; o que vaya a trabajar... Se lee rápido.
A continuación una chuletilla de cosas extraidas del susodicho..
Una vez hecho el checkout, el ciclo de trabajo típico es como sigue:
- Update your working copy
- svn update
- Make changes
- svn add
- svn delete
- svn copy
- svn move
- Examine your changes (estos comandos se pueden usar sin conectividad con el repositorio)
- svn status
- svn diff
- Se puede usar un programa externo
- svn revert
- Merge others' changes
- svn merge
- svn resolved
- elimina los ficheros temporales, cuando hay un conflicto
- Commit your changes
- svn commit
- svn log
- svn diff
- svn cat
- svn list
- svn import
- svn cleanup
- Revisiones
- Subversion lets you refer to these revisions by number, keyword, or date.
- Con el date, si queremos sacar lo mas cercano a una fecha (incluyendola) hay que mete el día posterior
- Las revisiones no van asociadas a archivo. Es decir si haces un checkout o un update de una revisión, te va a sacar todo lo que haya en esa rama con esa revisión (lo que hay en el HEAD, es decir lo mas actual con respecto a la revisión solicitada).
- Se pueden hacer copias con 'history'
- Los archivos pueden tener propiedades asociadas. Al ejecutar el comando se puede pedir que se ignoren.
- Y por supuesto hay muchos comandos mas... Todo bien cubierto en el documento enlazado...
- svn status --verbose --> saca info de todo, aunque no haya cambiado
- svn status --show-updates --verbose --> este ya contacta repositorio
- svn status -u -v --> la versión corta
- svn status -vu | grep "*" --> nos indica que no tenemos actualizado con respecto el repositorio
viernes, agosto 08, 2008
Web Frameworks
lunes, julio 07, 2008
Revisitando urls
Python tiene la función urlparse que permite obtener los diferentes componentes de una url.
Ejemplo:
(scheme,netLoc,path,parameters,query,fragment) = urlparse( url )
Vamos a ver que contiene cada parte....:
Si en la parte de la query ya tratamos los parametros, entonces ¿para que sirve parameters? Pues por lo visto son parámetros que pueden llevar cada 'segmento' del path. Eso si, no lo he visto en la vida.
Referencias:
Ejemplo:
(scheme,netLoc,path,parameters,query,fragment) = urlparse( url )
Vamos a ver que contiene cada parte....:
- scheme: Pues el esquema... ta claro.
- netLoc: La localización de red... (ojo! incluye el puerto)
- path: El path
- query: La query (lo que va después de ?)
- fragment: Esto es lo que va tras '#', al final de la url.
Si en la parte de la query ya tratamos los parametros, entonces ¿para que sirve parameters? Pues por lo visto son parámetros que pueden llevar cada 'segmento' del path. Eso si, no lo he visto en la vida.
Referencias:
- RFC 1738, Uniform Resource Locators (URL). This specifies the formal syntax and semantics of absolute URLs.
- RFC 1808, Relative Uniform Resource Locators. This Request For Comments includes the rules for joining an absolute and a relative URL, including a fair number of ``Abnormal Examples'' which govern the treatment of border cases.
- RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax. Document describing the generic syntactic requirements for both Uniform Resource Names (URNs) and Uniform Resource Locators (URLs).
¿Para Alma?
Suena muy fuerte el rumor de que Alma Technologies va a comprar a mi empresa....
Supongo que pronto sabremos algo.
Como cosa interesante el comentar que en Alma tienen un grupo dedicado a temas de tecnologías de búsquedas. Tienen un producto: SearchBox.
Supongo que pronto sabremos algo.
Como cosa interesante el comentar que en Alma tienen un grupo dedicado a temas de tecnologías de búsquedas. Tienen un producto: SearchBox.
miércoles, junio 25, 2008
Desde luego navegapolis me está gustando mucho. Espero sigan en la misma linea...
Su último post: Directivos sin talento.
Su último post: Directivos sin talento.
martes, junio 24, 2008
Avances en C++
Aunque hace siglos que no toco C++, hay que estar al tanto..
Veo en el blog de Herb Sutter una entrada sobre unos cambios interesantes: Type Inference vs. Static/Dynamic Typing.
Un cambio en el lenguaje muy prometedor.
Gracias a ese post he llegado a una librería que desconocía: POCO.
Y ya para acabar aquí unos links a unas charlas (que no he visto, pero me gustaría) sobre el futuro de C++.
Veo en el blog de Herb Sutter una entrada sobre unos cambios interesantes: Type Inference vs. Static/Dynamic Typing.
Un cambio en el lenguaje muy prometedor.
Gracias a ese post he llegado a una librería que desconocía: POCO.
Y ya para acabar aquí unos links a unas charlas (que no he visto, pero me gustaría) sobre el futuro de C++.
jueves, junio 19, 2008
Outsourcing
En Ingenieros de Primera tienen un artículo majetón sobre el Outsourcing : Aplicación del Outsourcing en las "Tecnologías de la Información".
Mucho mejor que los de la wikipedia [es][en].
Lo que no definen son algunos de los terminos usados: CIO (este no tengo claro a que se refiere exactamente), ROI, CTO.
Mucho mejor que los de la wikipedia [es][en].
Lo que no definen son algunos de los terminos usados: CIO (este no tengo claro a que se refiere exactamente), ROI, CTO.
martes, junio 10, 2008
refs refs refs
Hacia tiempo que Ian Bicking no publicaba nada. Acaba de publicar un post sobre Erlang.
Lo interesante ya no es el post en si, sino la cantidad de referencia que suelta en él, a saber:
Lo interesante ya no es el post en si, sino la cantidad de referencia que suelta en él, a saber:
- Monkey path: "is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, Javascript, Ruby, Perl, and Python) without altering the original source code."
- Bencode: "is the encoding used by the peer-to-peer file sharing system BitTorrent for storing and transmitting loosely structured data."
- JSON: "(JavaScript Object Notation) is a lightweight data-interchange format." En dicha página hay muchas referencias sobre JSON y Python.
- WebOb: "WebOb provides objects for HTTP requests and responses"
CSV en python
Python tiene un modulo para manejar CSVs: csv [PEP].
Buscando un poco seguro que podeis encontrar otras implementaciones. Está bien que la librería incorpore este manejo de archivos ya que es bastante común.
Una cosa interesante que tiene, son los dialectos. Veamoslo con un ejemplo:
Como podeis ver, el módulo incorpora dos dialectos para escribir/leer csv's del agrado de excel. Y es que hay que decir que no hay un estandar sobre CSV.
El hecho de estar mirando esto es porque estoy implementando un reader y andaba pensando si reutilizar este... En principio estoy por la labor... Si hay algo implementado mejor reutilizarlo ¿no?.
Lo que si que necesito de todas todas es un recubrimiento...
En principio hay dos cosas que me llaman la atención:
En el anterior ejemplo (descomentar una de las lineas que crean el 'dr') se imprime la primera línea que se lee del fichero, y se aborta.
Con los 3 constructores podemos ver la flexibilidad en la construcción, y como se comporta ante la presencia del argumento 'fieldnames' (si no se pasa => la primera linea se usa para formar las claves del diccionario).
Los parámetros que definen el formateo, pueden pasarse incluso en un diccionario.
Buscando un poco seguro que podeis encontrar otras implementaciones. Está bien que la librería incorpore este manejo de archivos ya que es bastante común.
Una cosa interesante que tiene, son los dialectos. Veamoslo con un ejemplo:
>>> import csv
>>> csv.list_dialects()
['excel-tab', 'excel']
Como podeis ver, el módulo incorpora dos dialectos para escribir/leer csv's del agrado de excel. Y es que hay que decir que no hay un estandar sobre CSV.
El hecho de estar mirando esto es porque estoy implementando un reader y andaba pensando si reutilizar este... En principio estoy por la labor... Si hay algo implementado mejor reutilizarlo ¿no?.
Lo que si que necesito de todas todas es un recubrimiento...
En principio hay dos cosas que me llaman la atención:
- Si al consctructor del DictReader se le pasan los campos, si el fichero tiene cabecera, la lee como una línea normal ¡Ojo!. Si no se pasan los campos toma la primera linea como claves para el diccionario.
- El constructor es muy flexible en su uso, a la hora de pasarle los parámetros.
- El modulo tiene una clase para intentar deducir el formato de un csv: Sniffer.
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
import csv
import sys
class midialecto(csv.Dialect):
delimiter = 'þ'
quotechar = '"'
lineterminator = '\r\n'
doublequote = True
skipinitialspace = True
quoting = csv.QUOTE_MINIMAL
csv.register_dialect("midialecto", midialecto)
campos = ['campo1','campo2']
f = open("ejemplo.csv","r")
# A descomentar la que mas nos guste
#
#dr = csv.DictReader(f,campos,None,None,'midialecto')
#dr = csv.DictReader(f,dialect='midialecto',fieldnames=campos)
#dr = csv.DictReader(f,dialect='midialecto')
for row in dr:
print row.keys()
print row.values()
sys.exit()
En el anterior ejemplo (descomentar una de las lineas que crean el 'dr') se imprime la primera línea que se lee del fichero, y se aborta.
Con los 3 constructores podemos ver la flexibilidad en la construcción, y como se comporta ante la presencia del argumento 'fieldnames' (si no se pasa => la primera linea se usa para formar las claves del diccionario).
Los parámetros que definen el formateo, pueden pasarse incluso en un diccionario.
jueves, junio 05, 2008
Garbage Collector revisited
He mejorada el programita de marras del post anterior. Ahí va la nueva versión:
Por cierto... la faq de python tiene pinta de estar muy bien. Me lo anoto como lectura futura.
Un ejemplo:
4.15 Why isn't all memory freed when Python exits?
Objects referenced from the global namespaces of Python modules are not always deallocated when Python exits. This may happen if there are circular references. There are also certain bits of memory that are allocated by the C library that are impossible to free (e.g. a tool like Purify will complain about these). Python is, however, aggressive about cleaning up memory on exit and does try to destroy every single object.
If you want to force Python to delete certain things on deallocation use the sys.exitfunc() hook to run a function that will force those deletions.
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
import gc
#gc.set_debug(gc.DEBUG_LEAK) # Será necesario ponerlo para rastrear los leaks
# a no ser que invoquemos explicitamente a collect()
#------------------------------------------------------------------------------
class MiList(list):
def __del__(self):
# El método del nos sirve, aparte de para sacar una traza
# para que el objeto sea uncollectable. Sin el __del__
# el recolector es capaz de recolectarlo correctamente.
print "En el __del__"
#------------------------------------------------------------------------------
# Collectable
print "-----> Collectable"
l = MiList()
del l
print "collect:", gc.collect()
print "garbage:", gc.garbage
#------------------------------------------------------------------------------
# Prueba de que con una lista normal no hay problema
# Pero que curioso que el metodo collect() devuelve 1
print "-----> Con una lista"
l2 = []
l2.append(l2)
del l2
print "collect:", gc.collect()
print "garbage:", gc.garbage
#------------------------------------------------------------------------------
# Uncollecable
# He metido dos instancias, para ver como collect() devuelve 2
# Y aparecen ambos en 'garbage'
print "-----> Uncollectable"
l = MiList()
l.append(l)
#l.pop() -> Con solo meter esto se resuelve el ciclo!!!
del l
l3 = MiList()
l3.append(l3)
del l3
#------------------------------------------------------------------------------
# ¿como ver dichos objetos que con Uncollectable?
print "collect:", gc.collect()
print "garbage:", gc.garbage # uncollectable objects ¡¡¡no muestra nada!!!
# A no ser que activemos por ejemplo el flact DEBUG_LEAK
# O hayamos invocado explicitamente a collect() ¡Ojo!
Por cierto... la faq de python tiene pinta de estar muy bien. Me lo anoto como lectura futura.
Un ejemplo:
4.15 Why isn't all memory freed when Python exits?
Objects referenced from the global namespaces of Python modules are not always deallocated when Python exits. This may happen if there are circular references. There are also certain bits of memory that are allocated by the C library that are impossible to free (e.g. a tool like Purify will complain about these). Python is, however, aggressive about cleaning up memory on exit and does try to destroy every single object.
If you want to force Python to delete certain things on deallocation use the sys.exitfunc() hook to run a function that will force those deletions.
Ejemplo de uncollectable object
Quería mostrar a una compi de curro, como funcionaba el tema del recolector de basuras, con lo cual me hice el siguiente programilla:
Si en el segundo bloque no hacemos el pop() vemos que si ponemos el flag DEBUG_LEAK, nos aparecerá el objeto 'uncollectable' en el atributo 'garbage'.
Por defecto no aparece.
Si se nos da una situación como esta, hay que resolverla a mano.
Lo de hacer el ejemplo con una clase que herede de List, en lugar de hacerlo con listas, es para mostrar cuando se invoca el método __del__.
El método __del__ se invocará antes de que se destruya el objeto, pero ¡ojo! si lo invocamos explicitamente no significa que se vaya a destruir y dicha memoria se vaya a liberar.
Otro apunto sobre la liberación de la memoria en python. La memoria se devolverá al gestor de memoria de python, que no significa que se libere al SO.
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
import gc
#gc.set_debug(gc.DEBUG_LEAK)
class MiList(list):
def __del__(self):
print "En el __del__"
# Collectable
print "-----> Collectable"
l = MiList()
del l
print "garbage:", gc.garbage
# Uncollecable
print "-----> Uncollectable"
l = MiList()
l.append(l)
#l.pop() -> Con solo meter esto se resuelve el ciclo!!!
del l
# ¿como ver dichos objetos que son Uncollectable?
print "garbage:", gc.garbage # uncollectable objects ¡¡¡no muestra nada!!!
# A no ser que activemos por ejemplo el flact DEBUG_LEAK
Si en el segundo bloque no hacemos el pop() vemos que si ponemos el flag DEBUG_LEAK, nos aparecerá el objeto 'uncollectable' en el atributo 'garbage'.
Por defecto no aparece.
Si se nos da una situación como esta, hay que resolverla a mano.
Lo de hacer el ejemplo con una clase que herede de List, en lugar de hacerlo con listas, es para mostrar cuando se invoca el método __del__.
El método __del__ se invocará antes de que se destruya el objeto, pero ¡ojo! si lo invocamos explicitamente no significa que se vaya a destruir y dicha memoria se vaya a liberar.
Otro apunto sobre la liberación de la memoria en python. La memoria se devolverá al gestor de memoria de python, que no significa que se libere al SO.
miércoles, mayo 28, 2008
Organizaciones sobre gestión de proyectos
Leyendo sobre Scrum veo que hay 3 organizaciones en el campo de la gestión de proyectos:
Hay organizaciones para tó, hoygan. Y como no las tres certifican.
Hay organizaciones para tó, hoygan. Y como no las tres certifican.
martes, mayo 27, 2008
miércoles, mayo 14, 2008
[Python-es] Preguntas de iniciado
Hay un hilo actual en python-es bastante interesante. Tengo que releerlo con calma, pero debido a un comentario de hoy, me veo en la necesidad de enlazarlo y copiar el comentario. Me ha paracido interesante.
"La preocupación por los supuestos peligros producto de la flexibilidad
de los lenguajes dinámicos es un mito sostenido las empresas de
software que pretenden convertir el arte de la programación en una
industria de producción en masa.
Pero tal y como señala Paul Graham
(http://www.paulgraham.com/knuth.html), programar es un arte. Y cuando
los programadores entienden esto, en contra de las ansias de
beneficios rápidos y sistemáticos de los accionistas de las empresas,
logran disfrutar su trabajo y hacerlo más rápido y con mayor calidad.
El problema es que los programadores artistas no tienen influencia en
los pensum de estudio de las universidades como si lo tienen las
grandes empresas como Sun y Microsoft, haciendo creer a la gente que
cuestiones ridículas como los getters y setter de Java son buenas
prácticas.
Es llamativo como profesores universitarios que no han desarrollado un
sistema completo enseñan como si fuese una religión los mecanismos de
encapsulación de un modo que entorpece terriblemente la productividad
de los programadores.
Python es un excelente lenguaje programación orientada a objetos, como
también lo es Ruby, y representan un verdadero salto evolutivo en
comparación con despropósitos como C++ y Java. Lo único que oculta esa
verdad es el enorme poder econñomico manifestado a travñes de
estrategia de lobby que siga permeando tanto al academia como a las
empresas."
La web enlazada paulgraham.com merece echarle una visita.
"La preocupación por los supuestos peligros producto de la flexibilidad
de los lenguajes dinámicos es un mito sostenido las empresas de
software que pretenden convertir el arte de la programación en una
industria de producción en masa.
Pero tal y como señala Paul Graham
(http://www.paulgraham.com/knuth.html), programar es un arte. Y cuando
los programadores entienden esto, en contra de las ansias de
beneficios rápidos y sistemáticos de los accionistas de las empresas,
logran disfrutar su trabajo y hacerlo más rápido y con mayor calidad.
El problema es que los programadores artistas no tienen influencia en
los pensum de estudio de las universidades como si lo tienen las
grandes empresas como Sun y Microsoft, haciendo creer a la gente que
cuestiones ridículas como los getters y setter de Java son buenas
prácticas.
Es llamativo como profesores universitarios que no han desarrollado un
sistema completo enseñan como si fuese una religión los mecanismos de
encapsulación de un modo que entorpece terriblemente la productividad
de los programadores.
Python es un excelente lenguaje programación orientada a objetos, como
también lo es Ruby, y representan un verdadero salto evolutivo en
comparación con despropósitos como C++ y Java. Lo único que oculta esa
verdad es el enorme poder econñomico manifestado a travñes de
estrategia de lobby que siga permeando tanto al academia como a las
empresas."
La web enlazada paulgraham.com merece echarle una visita.
martes, mayo 06, 2008
Paper a leer
Estoy leyendo un 'paper' que todo Arquitecto Software debería leer: Architectural Styles and the Design of Network-based Software Architectures.
Se trata de la tesis doctoral de Roy Fielding.
Se trata de la tesis doctoral de Roy Fielding.
miércoles, abril 23, 2008
Joomla
Hoy creo lo escuché por primera vez: Joomla [wiki] [otra][articulo].
Por lo visto es un CMS open source que están usando en yell.
En la wikipedia tienen un directorio de CMS open source, y una lista de CMS.
Desarrollados python tenemos:
Por lo visto es un CMS open source que están usando en yell.
En la wikipedia tienen un directorio de CMS open source, y una lista de CMS.
Desarrollados python tenemos:
jueves, abril 17, 2008
Java World
Que mundillo este de los Javeros... Tan lleno de siglas. Mundo en el que yo mas o menos me he mantenido al margen.
Tengo que reconocer que no me apasiona el lenguaje, ya que cuando surgió yo era muy de C++ y eso marca... Jeje.
Sin embargo el que ahora me apasiona es Python. Curioso... ¿Porque? Porque Python está mucho mas alejado de C++ que Java. Java es como que se queda a medio camino...
Mira si dejas ya un lenguaje como C++, lo dejas con todas las consecuencias. Eso si, está bien que apareciese Java y que exista. Tiene un nicho claro.
Hace tiempo estuve trasteando un poco con Java y CORBA, y realmente respecto a manejar CORBA con C++ es una gozada. Pero tras conocer python y volver a tocarlo, tengo mas fundamentos para ver que realmente se queda a medio camino. Hay que teclear mucho...
Un lenguaje como Python también tiene sus desventajas, pero para desarrolladores digamos 'avezados', que hagan buen uso de él, es una gozada.
Bueno... tras esta introducción a continuar con el típico post mio de recopilar enlaces que traten de un tema determinado...
Post que claramente tiene su origen en el curso que estoy haciendo... que me está sirviendo y mucho para refrescar estos temas.
Bueno al lio...
El curso que estoy haciendo es una introducción a J2EE. Bueno y ni siquiera eso, ya que que se quedan fuera los EJBs, u Enterprise Java Beans (que no confundir con los Java Beans). O los WebServices (esto ya si que es un cristo...), por mencionar un par de cosas. Vamos... que vemos solo parte realmente web, la que se ejecutarça en el servidor web.
Los EJBs son objetos distribuidos, mientras los Java Beans son objetos java reutilizables que deben implementar un determinado interfaz.
¿Entonces que es lo que vemos en el curso? Pues básicamente Servlets (que sería el equivalente a los Applets en un navegador, pero en el servidor) y JSPs . Bueno también las TagsLibs, y lo que de tiempo al final. Parece poco, pero es muy practico y ya se sabe... la practica lleva tiempo...
Sobre los JSPs... Los JSPs es una tecnología que te facilita la generación de Servlets (lo que se genera, dinámicamente, es un Servlet). Te facilita la integración de codigo Java (o no Java) con otro contenido (típicamente html). Vamos... es como si fuera una especie de template.
Como herramientas usamos.... adivina, adivinanza... Tomcat, Apache, y Eclipse.
Si usasemos EJBs ya no serviría Tomcat, ya que Tomcat sólo un contenedor de Servlets. Necesitaríamos un servidor de apliaciones, y seguramente habríamos usado JBoss, que es posiblemente el mas extendido.
Aunque los Servlets y las JSPs es la base del desarrollo web en Java, la tendencia es a usarlos poco directamente. La gente suele usar frameworks, siendo el mas oido struts (que es una implementación del patrón MVC).
Los frameworsks también tienen sus peros; siendo el principal el que mientras las cosas van bien, todos contentos, pero cuando van mal... a ver quien es el guapo que pilla que es lo que va mal.
Pero claro... como estos javeros lo que no quieren es tirar lineas de código... ;).
Contra esta tendencia a la complejidad y embarullar todo un poco han surgido cosillas como los POJO. También como reacción a lenguajes que vienen pisando fuerte: python y ruby.
Ya sobre como se da el curso en si...
Pues está bastante bien. Teoría la justa, la necesaria; y a practicar, que es como realmente se aprende.
Me preguntaba el cheriff si lo que estabamos viendo era la Pet Store... ¡Pues no! Estamos integrando una aplicacioncilla superchorra que se ha currado el profe. Y cuando digo integrando es realmente eso: nos dedicamos a montar la 'cola' entre el diseño web y la capa de negocio. Ambas cosas ya las tenemos hechas.
En Java BluePrints [wiki], aparte de la Pet Store, hay otra aplicación demo, la Java Adventure Builder Reference application; pero que no es tan popular. Los downloads.
Ummmmm, habrá que hacer una Python Pet Store ;)...
Y con esto y un bizcocho hasta mañana a las ocho (nunca mejor dicho).
miércoles, abril 16, 2008
Mas sobre PHP
Continuando un post anterior. Y tras este empape en tecnología web, no podia faltar leer algo mas sobre PHP.
No ya sobre como es el lenguaje, sino sobre su posición frente otras alternativas. Resumiendo:
Por lo que he podido leer PHP está muy fuertemente afianzado. Bueno a los links... Vía barrapunto he leido unos artículos interesantes:
No ya sobre como es el lenguaje, sino sobre su posición frente otras alternativas. Resumiendo:
- PHP: es el lider en muchos sitios populares. Se podría decir que es el lider a desbancar. El que debería escoger alguien que quiera montare algo web, sin experiencia en desarrollo.
- Java: gracias a la gran labor comercial que se ha hecho con él tiene un nicho enorme. Tiene ventajas sobre PHP, a cambio de complejidad. Este le gustaría mas a un Ingeniero Software, por el lenguaje y framework en si. Si ya estudiamos otros temas... puede que no. Los desarrollos son lentos y complejos. Un Ingeniero con PHP debería hacer las cosas tan correctamente como con Java, sólo necesitaría metodoloría.
- RoR: Nueva alternativa. Le gusta a los Javeros.
- Python: ¿tiene futuro? Si lo tiene será por el lenguaje en sí.
Por lo que he podido leer PHP está muy fuertemente afianzado. Bueno a los links... Vía barrapunto he leido unos artículos interesantes:
- Python never had a chance against PHP. Tiene una referencia al siguiente articulo de Ian Bicking que todavía no he leido: Why Web Programming Matters Most.
- What PHP deployment gets right
- The PHP Scalability Myth: Este no está tan bien como los anteriores pero tiene unos gráficos explicativos sobre las arquitecturas de J2EE y PHP. Esa parte está muy bien. No me gusta el concepto de escalabilidad que usa.
Parseando html
Hace tiempo estuvimos decidiendo que parser usar, para procesar el html en mi proyecto actual. En su momento fue una labor nada sencilla. Había dos requisitos básicos: tenía que ser rápido y se tenía que tragar html defectuoso. El ganador fue libxml2.
Hoy me he encontrado un blog muy interesante, el de Ian Bicking. En su blog tiene un artículo reciente sobre el parseo de html. En dicho artículo llega a la conclusión de que el mejor parser es lxml.
Llega a la misma conclusión que llegué yo, pero bajo unos requerimientos diferentes.
Sería interesante probar cuanto tiempo ganamos usando libxml2 y nuestras propias estructuras de datos frente a usar directamente lxml.
Hoy me he encontrado un blog muy interesante, el de Ian Bicking. En su blog tiene un artículo reciente sobre el parseo de html. En dicho artículo llega a la conclusión de que el mejor parser es lxml.
Llega a la misma conclusión que llegué yo, pero bajo unos requerimientos diferentes.
Sería interesante probar cuanto tiempo ganamos usando libxml2 y nuestras propias estructuras de datos frente a usar directamente lxml.
martes, abril 15, 2008
Documentando código
En el blog ya puse alguna mas entrada sobre documentación de código, al menos para python.
He visto en la wikipedia que tienen una comparativa de generadores de documentación.
He visto en la wikipedia que tienen una comparativa de generadores de documentación.
BDs libres
El otro día comentaba sobre BDs para almacenar pares de datos.
Para completar ese post ahí va uno para reseñar algunas de las BDs que disponemos for free:
La diferencia entre SQLite y las otras dos, es que las otras con sistemas cliente-servidor y SQLite es una libreria.
Con todo lo reseñados ya tenemos un abanico lo suficientemente amplio para escoger la solución que mas nos convenga... ¿no?
Para completar ese post ahí va uno para reseñar algunas de las BDs que disponemos for free:
La diferencia entre SQLite y las otras dos, es que las otras con sistemas cliente-servidor y SQLite es una libreria.
Con todo lo reseñados ya tenemos un abanico lo suficientemente amplio para escoger la solución que mas nos convenga... ¿no?
viernes, abril 11, 2008
Web framewoks
Este post viene por mi inquietud al respecto por varios motivos:
- Me gustaría hacer algo en la web
- Voy a dar un curso sobre J2EE. Realmente no me interesa NADA todo lo que tenga que ver con Java, pero si lo considero educativo. Tengo que aprovechar que dadas las circunstacias del proyecto ahora puedo... Ademas en mi proyecto actual si tenemos un servicio web montado con tecnología J2EE.
- Ayer JJ tras comentarle sobre lo de google, me volvió a hablar de RoR.
Si nunca has desarrollado para web (como yo) y tienes la libertad absoluta para hacerla, ¿con que lenguaje y framework hacerlo? La verdad... ambas cosas están relacionadas.
Empezando con el lenguaje, ¿que usar? php, ruby, java, perl, python, ...
Luego para cada lenguaje puedes disponer de varios frameworks, para liar mas la cosa...
Lo que si parece estar claro es que el dominante en los sitios populares es php.
Otra cosa curiosa es que los desarrolladores de Java tienen predilección por ruby y su RoR (Ruby on Rails). Como en este caso JJ.
Sobre python, entre los númerosos frameworks (a ver si encuentro un artículo bueno que los compare) que tiene el que parece está teniendo bastante tirón es django.
Sobre python no voy a profundizar, ya que será motivo para otro post.
Mi curiosidad se centra en RoR. A ver que hay detrás. Entonces que mejor que echar un vistazo a lo que hay por la red:
Notas finales:
- Al buscar la imagen, encontré esta página, que compara también php, java y ruby.
- Estas comparaciones hay que tomarlas con recelo ya que en muchos casos no son objetivas.
- Visto lo visto, como que paso ni de mirar mas fondo RoR.
jueves, abril 10, 2008
Autotools
¿Quien no conoce el famoso script configure?
Parece mentira que hasta la fecha nunca haya tenido que hacer uno. Pero creo que va siendo el momento...
Aprovechando que tenemos un momento de parón en el proyecto y la ocasión perfecta.
Estoy generando un rpm que tienen dependencias de unas librerías externas y claro... no está nada bien el tener rutas a piñón... Estoy ante la ocasión perfecta.
Pongamonos a ello...
Las principales herramientas de autotools son:
Una cosa superinteresante de automake es que te detecta las dependencias dinámicamente. Cuando haces un makefile a mano, son estáticas, ya que tu las tienes que meter en las reglas. O bien montarte tu dicho mecanismo. Pues bien... automake esto te lo da.
Este post lo iré actualizando sobre la marcha..
Parece mentira que hasta la fecha nunca haya tenido que hacer uno. Pero creo que va siendo el momento...
Aprovechando que tenemos un momento de parón en el proyecto y la ocasión perfecta.
Estoy generando un rpm que tienen dependencias de unas librerías externas y claro... no está nada bien el tener rutas a piñón... Estoy ante la ocasión perfecta.
Pongamonos a ello...
Las principales herramientas de autotools son:
- automake [wiki]: nos permitirá generar mejores makefiles, mas portables, ...
- autoconf [wiki]: es la que nos va asegurarnos que disponemos de todo lo necesario. Usa para ello macros escritas en M4. Existe un repositorio de macros, por si necesitamos macros aparte de las que ya acompañan al paquete.
- libtool [wiki]: Por lo visto si lo que queremos es generar una libreria, la necesitaremos.
Una cosa superinteresante de automake es que te detecta las dependencias dinámicamente. Cuando haces un makefile a mano, son estáticas, ya que tu las tienes que meter en las reglas. O bien montarte tu dicho mecanismo. Pues bien... automake esto te lo da.
Este post lo iré actualizando sobre la marcha..
Pares clave-valor persistentes
Para almacenar persistentemente pares clave-valor disponemos de GDBM - The GNU database manager. La cual es la reimplementacion de dbm para gnu.
Como no podia ser de otra manera tenemos un módulo en python para hacer uso de ella.
Otra implementacion es bdb.
Como otros almacenamientos persistentes tenemos:
Como no podia ser de otra manera tenemos un módulo en python para hacer uso de ella.
Otra implementacion es bdb.
Como otros almacenamientos persistentes tenemos:
Mondrian Code Review On The Web
Creo que fue en el video sobre Google App Engine, donde escuché sobre Mondrian.
Aprovechando que ahora tengo tiempo lo he estado viendo... y merece la pena verlo.
La charla, impartida por Guido, empieza mostrando lo que usaban antes de que implementaran Mondrian, lo que aporta Mondrian y sus ventajas. Básicamente usaban varios scripts.
Ah! antes de nada comenta sobre la filosofía de trabajo. Parte de él es hacer reviews del código fuente.
Hacer revisiones es una alternativa a la xp. Eso si con el mismo objetivo, mejorar la calidad. ¿Donde he visto yo estas practicas? ¿En ningún sitio?
Gracias al video me enterado de cosillas, como por ejemplo que prácticamente no usan branches, y que como sistema de control de versiones usan Perforce [wikipedia][site].
Lo que hace en pocas palabras
Lo que tienen ahora es una aplicación web que gestiona todo el tema de las reviews.
Como desarrollador te revisan y revisas. En la pantalla puedes ver en 2 paneles codigo antiguo y nuevo, poner comentarios....
Ademas se hace uso del correo para enviar notificaciones, ...
Todas estas cosillas siempre se guardan, usandose para ello BigTable+GFS.
Lógicamente también tienen que acceder al servidores de Perforce, y a los entornos de los usuarios (soportan SSH y NFS).
Como lo hacen
Guido comenta que casi podría correr en una maquina, ya que casi todo el trabajo pesado se hace fuera (Perforce, GFS, rendering de html), pero que lo tienen montado en dos maquinas: una para el mail server y otra para el web server.
Y como no podría ser de otra manera usan python a saco: el mail server es wsgiref (multithread y estandard) y el mail server smtpd.py (monothread).
El interfaz es html+css, usando las templates de django, y como no podía ser de otra manera, usan AJAX.
Para hacer los diffs usan la librería de python difflib.
Tanto smtpd, como wsgiref y difflib son módulos estándares de la distribución de python.
miércoles, abril 09, 2008
Visual Test
Hablando ayer con mi futura cuñaaaaaaaa, le comentaba que hace años mil yo usaba Visual Test para la automaticación de pruebas de interfaces graficas.
El motivo de la conversación era porque estabamos generando .avi's a parter de dvds. El problema de dejar lanzado un lote de generaciones es que si te sale un popup, por algun problema o alerta, el proceso se para (usamos autogk). Le comenté que eso se podría solventar con un script realizado con visual test, y de ahí este dejavú.
La verdad es que era supercomodo de usar. Te grababas las accciones y automáticamente se generaba un script. Script que luego podrias adaptar.
Con N de estos scripts te montabas ya una batería de pruebas. Era la caña...
Me he quedao sorprendido de, ya no sólo que pasara a ser de Rational, sino que Rational ha pasado a ser de IBM.
Esta es la lista de los productos de rational.
Y como no, el sucesor de visual test está: IBM Rational Robot.
Referencias:
- GUI automation.
- GUI Testing Tools
- DogTail: como no... en python algo tenía que haber.
- Software QA Resouces Center. (SQARC)
- Linux Desktop (GUI Application) Testing Project (LDTP)
- En APTest hay un listado todavía mas impresionante que el de SQARC.
- Para la automatización en unix, disponemos de expect.
- Como no podia ser de otra manera hay un flavour en python: pexpect.
- Y una par de herramientas for free para windows: autohotkey y autoit.
martes, abril 08, 2008
Google App Engine
He flipado un poco cuando lo he visto en barrapunto. Esto puede ser un buen empujón para python y django.
Este artículo lo cuenta muy clarito.
Y os recomiendo ver los videos en youtube del Campfire One: Google App Engine.
De momento su uso está cerrado, pero puedes indicar que te avisen cuando vuelvan a ofrecer el servicio. De momento para probar y enredar se puede usar el SDK en local.
La idea de todo esto, es desarrollar y olvidarte del manteniento de la aplicación online, de cuanta maquina necesitas, cuanto espacio en disco, el que este online 24x7,.... Google se ocupa de todo esto.
¿Interesante verdad?
Bueno... la chicha:
Este artículo lo cuenta muy clarito.
Y os recomiendo ver los videos en youtube del Campfire One: Google App Engine.
De momento su uso está cerrado, pero puedes indicar que te avisen cuando vuelvan a ofrecer el servicio. De momento para probar y enredar se puede usar el SDK en local.
La idea de todo esto, es desarrollar y olvidarte del manteniento de la aplicación online, de cuanta maquina necesitas, cuanto espacio en disco, el que este online 24x7,.... Google se ocupa de todo esto.
¿Interesante verdad?
Bueno... la chicha:
- google apps engine: el home, api, sdk, doc, articles, ...
- aplicaciones ya hechas
jueves, abril 03, 2008
Python IDEs
Jonathan Ellis comenta que a raiz de un post en un blog ha estado organizando el listado de los editores python 'reales' existentes.
También hay un listado de editores que tienen algún soporte para python, pero que no pueden ser considerados editores 'reales'.
La diferencia entre los primeros y los segundos está principalmente en las facilidades que te den para hacer introspección, depuración y ayuda a la codificación.
También hay un listado de editores que tienen algún soporte para python, pero que no pueden ser considerados editores 'reales'.
La diferencia entre los primeros y los segundos está principalmente en las facilidades que te den para hacer introspección, depuración y ayuda a la codificación.
martes, marzo 18, 2008
RAID for dummies
Bueno... tras leer sobre RAID (debido al NAS que me he pillado) ahí van unas notas breves:
- Del RAID 2 y 3 nos podemos olvidar.
- RAID 0. Los datos se reparten en varios discos. Acceso más rapido tanto en lectura como escritura. No hay redundancia.
- JBOD: No es realmente RAID 0, pero es parecido. Sirve para ver varios discos como uno solo.
- Con RAID 1 (data mirroing) tenemos un disco espejo. Con lo cual es la redundancia más cara. No ganamos velocidad en lectura pero si en escritura (normalmente).
- RAID 4: división por bloques on un disco dedicado a la paridad.
- RAID 5: se usa mucho, porque se obtiene redundancia a bajo coste. Es mas lento en escritura, ya que hay que calcular los bloques de paridad, que se van escribiendo (es importante estudiar el tipo de acceso de escritura para saber si nos va a liminar). Son necesarios 3 discos. Puede recuperarse ante el fallo de un disco. Pero no ya de un fallo de un segundo disco.
- RAID 6: protege ante fallo de dos discos.
- RAID 5E y 6E
- RAIDs anidados.
- .../...
miércoles, marzo 05, 2008
Compartiendo un fichero entre procesos
Imaginaros que se os da la situación en la cual necesitais compartir un archivo entre procesos.
Vamos a ver que opciones tenemos:
[1] Usar como lock un archivo que creamos. Se puede usar la llamada os.open() para crear un archivo en exclusiva. El proceso que lo pueda crear tiene via libre para usar ya el fichero que nos interesa. Hay que tener cuidado con proporcionar los mecanismos para no dejar el lock por ahí.
[2] Usar los mecanismos que nos proporciona el OS para bloquear ficheros. Llamada fcntl.lockf().
A continuación voy a copiar dos scripts que demuestran su uso. Ejecutar en primer lugar uno.py e inmediatamente dos.py en otro terminal.
En estos scripts se hace un open() se bloquea el archivo y despues un close().
Una alternativa seria el tener siempre el open() hecho y simplemente hacer el lockf(). Supongo que esto funcionaría pero no lo he probado.
Ya para acabar, comentar la importancia de hacer el seek() en el segundo script para poder escribir en lugar adecaudo del fichero.
uno.py
dos.py
Vamos a ver que opciones tenemos:
[1] Usar como lock un archivo que creamos. Se puede usar la llamada os.open() para crear un archivo en exclusiva. El proceso que lo pueda crear tiene via libre para usar ya el fichero que nos interesa. Hay que tener cuidado con proporcionar los mecanismos para no dejar el lock por ahí.
[2] Usar los mecanismos que nos proporciona el OS para bloquear ficheros. Llamada fcntl.lockf().
A continuación voy a copiar dos scripts que demuestran su uso. Ejecutar en primer lugar uno.py e inmediatamente dos.py en otro terminal.
En estos scripts se hace un open() se bloquea el archivo y despues un close().
Una alternativa seria el tener siempre el open() hecho y simplemente hacer el lockf(). Supongo que esto funcionaría pero no lo he probado.
Ya para acabar, comentar la importancia de hacer el seek() en el segundo script para poder escribir en lugar adecaudo del fichero.
uno.py
import os
import fcntl
import time
#--- Creamos el fichero
h = open("kk.txt","w")
h.write("hello\n")
h.close()
#--- Ahora lo abrimos bloquendolo
h = open("kk.txt","a")
fcntl.lockf(h.fileno(),fcntl.LOCK_EX)
print "Hemos pillado el lock y n os vamos a dormir"
time.sleep(15)
print "escribimos"
h.write("hello\n")
print "Tam: ", h.tell()
#h.flush() -> He procado sin el flush y funciona correctamente,
# pero con el, podría ser mas seguro.
# Adicionalmente está la llamada os.fsync().
# Si queremos mas control en el modo de apertura de los
# ficheros tenemos que usar la llamada os.open().
# Por ejemplo si los queremos crear en exclusiva.
print "Liberamos el lock y cerramos"
fcntl.lockf(h.fileno(),fcntl.LOCK_UN)
h.close()
dos.py
import os
import fcntl
import time
#--- Abrimos
#
# Nota: Si usamos LOCK_NB en lockf al adquirirlo y no podemos,
# nos da un error.
h = open("kk.txt","a")
#fcntl.lockf(h.fileno(),fcntl.LOCK_EX|fcntl.LOCK_NB)
fcntl.lockf(h.fileno(),fcntl.LOCK_EX)
print "Hemos pillado el lock y n os vamos a dormir"
#--- Lo usamos
h.seek(0,2)
print "Tam: ", h.tell()
#--- Cerramos
print "Liberamos el lock y cerramos"
fcntl.lockf(h.fileno(),fcntl.LOCK_UN)
h.close()
lunes, febrero 25, 2008
urllib vs urllib2
Haciendo unas pruebecillas con la página de la wikipedia de mi signo chino, me pasaba una cosa curiosa que era que en la maquina en la que estaba ejecutando mi código me daba un error:
Pero sin embargo, haciendo un wget, si que la obtenía...
Se me ocurre probar con urllib en lugar de con urllib2 y si que la obtengo. ¿Mande?
Solución ñapa temporal :pppp:
¡Dios! ¡soy un lumbreras!
Bueno seamos serios.... tras probar mis cosillas gracias a la ñapa, procedamos a mirar que es lo que realmente está pasando...
Pues lo que está pasando es que urllib2 está enviando unos headers al servidor web que no le molan...
La solución es cambiar el user agent.
Para ello lo que tenemos que hacer es proceder del siguiente modo (por ejemplo):
Referencias:
>>> import urllib2
>>> urllib2.urlopen("http://es.wikipedia.org/wiki/Rata")
Traceback (most recent call last):
File "", line 1, in ?
File "/usr/lib/python2.4/urllib2.py", line 130, in urlopen
return _opener.open(url, data)
File "/usr/lib/python2.4/urllib2.py", line 364, in open
response = meth(req, response)
File "/usr/lib/python2.4/urllib2.py", line 471, in http_response
response = self.parent.error(
File "/usr/lib/python2.4/urllib2.py", line 402, in error
return self._call_chain(*args)
File "/usr/lib/python2.4/urllib2.py", line 337, in _call_chain
result = func(*args)
File "/usr/lib/python2.4/urllib2.py", line 480, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden
Pero sin embargo, haciendo un wget, si que la obtenía...
Se me ocurre probar con urllib en lugar de con urllib2 y si que la obtengo. ¿Mande?
Solución ñapa temporal :pppp:
try:
h = urllib2.urlopen(theUrl)
except:
h = urllib.urlopen(theUrl)
¡Dios! ¡soy un lumbreras!
Bueno seamos serios.... tras probar mis cosillas gracias a la ñapa, procedamos a mirar que es lo que realmente está pasando...
Pues lo que está pasando es que urllib2 está enviando unos headers al servidor web que no le molan...
La solución es cambiar el user agent.
Para ello lo que tenemos que hacer es proceder del siguiente modo (por ejemplo):
userAgent = 'Mozilla' # Por ejemplo
headers = { 'User-Agent' : userAgent }
req = urllib2.Request(theUrl, None, headers)
response = urllib2.urlopen(req)
thePage = response.read()
Referencias:
- urllib2 - The Missing Manual[y aqui equivalente]
- Y otro artículo del mismo site, sobre el manejo de cookies. Nota: hay más artículos interesantes.
- Listado de user agents.
lunes, febrero 04, 2008
martes, enero 29, 2008
Brad Fitzpatrick
De una cosa que se oye hablar últimamente: opensocial.
Y tambien de openid.
Detrás de ambos proyecto hay un nombre común: Brad Fitzpatrick.
Y tambien de openid.
Detrás de ambos proyecto hay un nombre común: Brad Fitzpatrick.
jueves, enero 24, 2008
¿Escalan bien los lenguajes dinámicos?
A través de este post de barrapunto, llego a éste articulo de The Server Side.
Es de interesante lectura, no solo por el artículo, sino ademas por todas las referencias que contiene.
Parece que todo viene a colacion del proyecto chandler.
Es de interesante lectura, no solo por el artículo, sino ademas por todas las referencias que contiene.
Parece que todo viene a colacion del proyecto chandler.
TinyURL
Hoy me he encontrado una pequeña herramienta web, que puede ser muy util, TinyURL. No sólo proque nos puede ayudar a hacer mas manejables ciertas urls, sino porque nos puede permitir no favorecer el algoritmo de google, por el tema del enlazado. Se sepa... ;). O bien por lo que sea porque queramos enmascarar una url hasta el momento de pincharla.
miércoles, enero 16, 2008
martes, enero 15, 2008
lunes, enero 14, 2008
Ha surgido un thread muy interesante en python-es a raiz de que python ha sido declarado por TIOBE lenguaje del año 2007.
sábado, enero 05, 2008
jueves, noviembre 15, 2007
Python en Linux-magazine
El número 32 de Linux Maganize va dedicado a python [vía la lista python-es].
miércoles, noviembre 14, 2007
Parseando CSS en python revisited
Una tercera entrada sobre el tema. Las anteriores:
Debido a la lentitud de cssutils (usé la versión 0.9.1b3) pobré libcroco y las diferencias de tiempo eran brutales (en un ejemplo real, pues ('real time') de procesar en 0,1 seg. a 0,4 seg.
Para la funcionalidad que necesito, me valen ambas, con lo cual en mi caso la elección está clara, ya que el tiempo de procesamiento me importa. Mi uso de la librería es muy rudimentario. Lo que realmente me interesa es el parseo en si, que me lo den, luego yo ya manejaré los datos a mi antojo...
Ahora bien, si el tiempo no te importan pues lo suyo es usar csstuils, porque libcroco te obliga a implementar bindings, ya que es C.
Con respecto a cssutils, comentar que ultimamente veo que el proyecto ha estado muy activo (van por la version 0.9.4a3), y que ahora está alojado en google code.
Bindings a libcroco
Para los bindings usé swig. No por decisión propia, sino porque ya lo usabamos.... No se si es lo mejor, pero es lo que hay.
En un primer intento lo que hice fue intentar atacar el interfaz de la librería. ¡Piiiiiip! Error.
Inabordable.
La solución fué hacer un recubrimiento en C sobre la librería, y hacer los bindings para ese recubrimiento.
En mi caso, el fichero de interfaz quedó como sigue:
%module css2av
%header %{
#include "css2av.h"
%}
typedef struct
{
char *selector;
char *declaration;
} AVStyleRule;
extern long numRules;
void freeResouces();
void process(const char *buffer,
long len
);
AVStyleRule *getRule(int index);
%include cpointer.i
%pointer_functions(AVStyleRule, AVStyleRulePtr)
Ya veis que api complejo y sofisticado me gasto ;)...
¿Que es necesario para generar los bindings?
import css2av
css2av.process(data,len(data))
for i in range(css2av.cvar.numRules):
styleRule = css2av.getRule(i)
print "Regla:",
css2av.AVStyleRulePtr_value(styleRule).selector,
css2av.AVStyleRulePtr_value(styleRule).declaration
css2av.freeResouces()
Como se puede apreciar, el código no es muy pythoniano. La solución es hacer un recubrimiento a los bindings mas pythoniano.
Debido a la lentitud de cssutils (usé la versión 0.9.1b3) pobré libcroco y las diferencias de tiempo eran brutales (en un ejemplo real, pues ('real time') de procesar en 0,1 seg. a 0,4 seg.
Para la funcionalidad que necesito, me valen ambas, con lo cual en mi caso la elección está clara, ya que el tiempo de procesamiento me importa. Mi uso de la librería es muy rudimentario. Lo que realmente me interesa es el parseo en si, que me lo den, luego yo ya manejaré los datos a mi antojo...
Ahora bien, si el tiempo no te importan pues lo suyo es usar csstuils, porque libcroco te obliga a implementar bindings, ya que es C.
Con respecto a cssutils, comentar que ultimamente veo que el proyecto ha estado muy activo (van por la version 0.9.4a3), y que ahora está alojado en google code.
Bindings a libcroco
Para los bindings usé swig. No por decisión propia, sino porque ya lo usabamos.... No se si es lo mejor, pero es lo que hay.
En un primer intento lo que hice fue intentar atacar el interfaz de la librería. ¡Piiiiiip! Error.
Inabordable.
La solución fué hacer un recubrimiento en C sobre la librería, y hacer los bindings para ese recubrimiento.
En mi caso, el fichero de interfaz quedó como sigue:
%module css2av
%header %{
#include "css2av.h"
%}
typedef struct
{
char *selector;
char *declaration;
} AVStyleRule;
extern long numRules;
void freeResouces();
void process(const char *buffer,
long len
);
AVStyleRule *getRule(int index);
%include cpointer.i
%pointer_functions(AVStyleRule, AVStyleRulePtr)
Ya veis que api complejo y sofisticado me gasto ;)...
¿Que es necesario para generar los bindings?
- Pues los .h y .c del codigo c
- el .i (el codigo mostrado)
- Generar los bindings: swig -python [fichero]
- Compilar nuestro código de interfaz (el .c para obtener el .o)
- Compilar el código de los bindings (fichero [nombre_interfaz]_wrap.c ). Para compilarlo usar la opción -c del gcc e incluir con -L .../python
y -L .../python /config - Generar la librería: gcc -shared [nombre].o [nombre]_wrap.o -o _[nombre].so -L[ruta] -lcroco-0.6 -lglib-2.0 -lxml2 -lz -lm
import css2av
css2av.process(data,len(data))
for i in range(css2av.cvar.numRules):
styleRule = css2av.getRule(i)
print "Regla:",
css2av.AVStyleRulePtr_value(styleRule).selector,
css2av.AVStyleRulePtr_value(styleRule).declaration
css2av.freeResouces()
Como se puede apreciar, el código no es muy pythoniano. La solución es hacer un recubrimiento a los bindings mas pythoniano.
lunes, noviembre 12, 2007
lunes, octubre 29, 2007
rpm
rpm.org es el SITIO de referencia para documentarse sobre rpm.
Para comenzar el tutorial de gurulabs está realmente bien; además incluye un ejercicio para practicar...
He visto también que hay unos bindings para python.
Actualización
Para comenzar el tutorial de gurulabs está realmente bien; además incluye un ejercicio para practicar...
He visto también que hay unos bindings para python.
Actualización
- El ejercicio de gurulabs (aunque no lo he hecho) tiene realmente muy buena pinta. Es amplio (tiempo estimado 1.5 horas).
- En el tutorial vienen también urls de recursos varios.
- Ya en plan documentación lo mejor que he visto por ahí es:
- Unos articulos de IBM, "Packaging software with RPM": [Part 1][Part 2][Part 3]
- Un howto.
- El articulo (un poco obsoleto) maximum rpm.
- Y por supuesto siempre nos quedará la wikipedia.
FHS
En linux la estructura de directorios sigue un estandar, el cual es conocido por Filesystem Hierarchy Standard (FHS). Es interesante entender esa estructura, para saber a la hora de desplegar una aplicación que estemos desarrollando donde tiene que ir cada fichero.
Otras siglas sobre estandarización relacionadas: POSIX (Portable Operating System Interface) y LSB (Linux Standard Base).
Otras siglas sobre estandarización relacionadas: POSIX (Portable Operating System Interface) y LSB (Linux Standard Base).
jueves, octubre 25, 2007
Probando distutils
Sobre distutils ya había hablado en: Instalando con Python.
Recientemente hemos cambiado tanto la estructura del proyecto en el subversion como en la instalación, con lo cual los antiguos setup.py ya no nos sirven (hechos para distutils).
Pero no solo queda ahí la cosa, sino que vamos a instalar con rpms. Una opción hubira sido el crear ls 'specs' de los rpms a manubrio, pero me han recomendado hacerlo con distutils, y luego si hay que modificar algo, pues hacerlo, pero de esta manera no las tienes que crear desde cero.
La verdad.... me parece una muy buena idea, pero no sólo por ese posible ahorre de trabajo, sino que ademas podemos seguir desplegando de la manera normal (directamente) o generar un tar.gz.
Todo son ventajas...
Tras hacer el setup.py he mirado a ver que diferencias hay con setuptools [ibm article]. Por lo que parece son similares; siendo la mayor ventaja que ofrece setuptools, que te busca los paquetes a instalar y se asegura de resolver las dependencias.
Otra cosa que permite setuptools es generar 'eggs files'; y contiene EasyInstall.
Volviendo al tema que nos ocupa... cuando tienes una estructura un poco complicada no te queda mas remedio que meter en el setup.py funciones de utilidad para tu problemática concreta.
En mi caso, el mayor problemilla que he tenido es que las rutas de instalación y del SVN no son exactas, con lo cual tengo que hacer un mapeo entre el paquete que se instala, y la ruta donde está el código.
Esto se solventa con los parametros packages y package_dir, lo que hago es recorrer recursivamente el arbol del SVN para obtener las rutas a los paquetes, para a partir de ellas generar el nombre del paquete destino y definir a que directorio del SVN se corresponde.
En el caso de los datos, el parametro data_files, permite resolver esta problemática sin necesidad de ningun parámetro adicional.
Como documentación, el artículo que enlacé antes (Spreading python applications) está muy bien; asi como la documentación estándar.
Un par de notas finales:
Recientemente hemos cambiado tanto la estructura del proyecto en el subversion como en la instalación, con lo cual los antiguos setup.py ya no nos sirven (hechos para distutils).
Pero no solo queda ahí la cosa, sino que vamos a instalar con rpms. Una opción hubira sido el crear ls 'specs' de los rpms a manubrio, pero me han recomendado hacerlo con distutils, y luego si hay que modificar algo, pues hacerlo, pero de esta manera no las tienes que crear desde cero.
La verdad.... me parece una muy buena idea, pero no sólo por ese posible ahorre de trabajo, sino que ademas podemos seguir desplegando de la manera normal (directamente) o generar un tar.gz.
Todo son ventajas...
Tras hacer el setup.py he mirado a ver que diferencias hay con setuptools [ibm article]. Por lo que parece son similares; siendo la mayor ventaja que ofrece setuptools, que te busca los paquetes a instalar y se asegura de resolver las dependencias.
Otra cosa que permite setuptools es generar 'eggs files'; y contiene EasyInstall.
Volviendo al tema que nos ocupa... cuando tienes una estructura un poco complicada no te queda mas remedio que meter en el setup.py funciones de utilidad para tu problemática concreta.
En mi caso, el mayor problemilla que he tenido es que las rutas de instalación y del SVN no son exactas, con lo cual tengo que hacer un mapeo entre el paquete que se instala, y la ruta donde está el código.
Esto se solventa con los parametros packages y package_dir, lo que hago es recorrer recursivamente el arbol del SVN para obtener las rutas a los paquetes, para a partir de ellas generar el nombre del paquete destino y definir a que directorio del SVN se corresponde.
En el caso de los datos, el parametro data_files, permite resolver esta problemática sin necesidad de ningun parámetro adicional.
Como documentación, el artículo que enlacé antes (Spreading python applications) está muy bien; asi como la documentación estándar.
Un par de notas finales:
- para pruebas podeis usar la opción --dry-run
- con --verbose os indica si os faltan ficheros __init__.py
viernes, octubre 19, 2007
Ver correctamente todos los caracteres con vi
Si os pasa que no veis correctamente algunos caracteres en vi, como por ejemplo los acentos, estais ante un problema con el encoding.
Puede ser porque no tengais correctamente definida la variable LAN, es valor correcto para el español es 'es_ES'.
Puede ser porque no tengais correctamente definida la variable LAN, es valor correcto para el español es 'es_ES'.
jueves, octubre 11, 2007
jueves, octubre 04, 2007
Ultraedit
Ahora para currar utilizo Windows XP Pro, lo cual me forzó a migrar a la version 13 de ultraedit, ya que la anterior que tenía no funcionaba correctamente.
Pues bien... la version que tengo ahora mismo delante, la 13.10a+1 me ha sorprendido muy gratamente. Han mejorado y mucho el ya util menú FTP/TELNET.
El soporte a ftp lo llevan teniendo desde hace siglos, luego metieron el de sftp, y ahora puedes establecer conexiones a ssh. No se si ya estaba y no me había dado cuenta o es nuevo. Yo creo que es nuevo.
Lo que si que es seguro es que han metido la opciones 'account manager' y 'ftp browser'. La segunda está genial, ya que nos evitará el instalar un cliente de ftp/sftp.
Pues bien... la version que tengo ahora mismo delante, la 13.10a+1 me ha sorprendido muy gratamente. Han mejorado y mucho el ya util menú FTP/TELNET.
El soporte a ftp lo llevan teniendo desde hace siglos, luego metieron el de sftp, y ahora puedes establecer conexiones a ssh. No se si ya estaba y no me había dado cuenta o es nuevo. Yo creo que es nuevo.
Lo que si que es seguro es que han metido la opciones 'account manager' y 'ftp browser'. La segunda está genial, ya que nos evitará el instalar un cliente de ftp/sftp.
miércoles, octubre 03, 2007
Remote Diff
Lo mas relevante en google sobre como hacer un remote diff.
La mejor solución en un comentario, que es usando ssh: ' ssh remotehost ‘cat remotefile’ | diff - localfile'.
La mejor solución en un comentario, que es usando ssh: ' ssh remotehost ‘cat remotefile’ | diff - localfile'.
miércoles, septiembre 26, 2007
Fijar variables de entorno de la shell desde python
Para algo que tengo que hacer necesitaría fijar el entorno de la shell desde python, pero en principio esto no es posible.
Quiero decir, que desde python tal cual no se puede, ya que en UNIX desde un proceso hijo no se puede modificar el entorno del padre.
Una opción sería hacer un 'shell script' en el que se invoque un script python con cada variable a configurar, y que el script devuelva el valor para esa variable.
Pero en mi caso me interesaria mas otra cosa, y es que el script de la shell, el que invoca a python, no sepa nada de que variables de entorno hay que configurar.
La solución es parecida: el script python generar el codigo shell a ejecutar sacandolo por stdout y la shell lo ejecuta.
Mas info aquí.
Y ahora la solución que voy a aplicar, mostrada con un ejemplo muy tonto.
Código python que define las variables (prueba.py):
print "KK1=kk1"
print "KK2=kk2"
La shell que lo invoca:
for cmd in `python $PWD/prueba.py`; do
export $cmd
done
Sencillo ¿verdad?
Quiero decir, que desde python tal cual no se puede, ya que en UNIX desde un proceso hijo no se puede modificar el entorno del padre.
Una opción sería hacer un 'shell script' en el que se invoque un script python con cada variable a configurar, y que el script devuelva el valor para esa variable.
Pero en mi caso me interesaria mas otra cosa, y es que el script de la shell, el que invoca a python, no sepa nada de que variables de entorno hay que configurar.
La solución es parecida: el script python generar el codigo shell a ejecutar sacandolo por stdout y la shell lo ejecuta.
Mas info aquí.
Y ahora la solución que voy a aplicar, mostrada con un ejemplo muy tonto.
Código python que define las variables (prueba.py):
print "KK1=kk1"
print "KK2=kk2"
La shell que lo invoca:
for cmd in `python $PWD/prueba.py`; do
export $cmd
done
Sencillo ¿verdad?
Editores de texto
Tenía una versión de ultraedit de evaluación, que me ha caducado. Esto me ha motivado a usar vim (a ver si lo aprendo un poco mejor...).
Anteriormente usaba ultraedit, accediendo a las maquinas por SFTP...
Hablando con Marcos me comenta de dos editores que están bien, que el usa:
Básicamente mientras pase esta temporada con vim, lo que necesito es un editor (ligero) para editar ficheros en local (y super importante, que tenga pestañas)
Actualización
Tras haber escrito lo anterior he buscado por comparativas, y paginas con listado de editores. Ahí van mas links:
Lo que no se (en la comparativa no viene) si hay alguno que soporte edición en modo columna (aparte de ultraedit).
Anteriormente usaba ultraedit, accediendo a las maquinas por SFTP...
Hablando con Marcos me comenta de dos editores que están bien, que el usa:
- scite [wikipedia].
- ulipad. Es un editor de python, y que tiene buena pinta. Puede acceder por ftp, pero parece que no por stp. Ha sido llevado a code.google.
Básicamente mientras pase esta temporada con vim, lo que necesito es un editor (ligero) para editar ficheros en local (y super importante, que tenga pestañas)
Actualización
Tras haber escrito lo anterior he buscado por comparativas, y paginas con listado de editores. Ahí van mas links:
- Tabla comparativa.
- Y comparativa wikipedia.
- En dmoz.
- Listados: [1][2][wikipedia]
- Articulillos: [1]
Lo que no se (en la comparativa no viene) si hay alguno que soporte edición en modo columna (aparte de ultraedit).
NetWinShit
Otro post para mostrar carencias de windows bastante irritantes. Esta vez relacionadas va de temas de red.
- Imposiblidad de poder tener perfiles de red. Aunque debe de haber aplicaciones externas que lo permitan... O en caso contrario siempre se puede usar una aplicación de testeo, que imite a un usuario.
- Imposibilidad de tener configurado mas de un dominio. Para poder conectarte a un dominio, necesitas una cuenta de administración del dominio, por lo que normalmente no lo harás tu, como usuario que eres. Lo hará un administrdor por tí. Pues bien, imaginate que con tu portatil megachulo estas unos días en un edificio y otros en otro, y esos tienen dominios diferentes... Pues bien, no puedes tener ambos configurados y que cuando te salga la ventana de login, selecciones el que te interesa...
martes, septiembre 25, 2007
domingo, septiembre 23, 2007
El porqué del __name__ == "__main__"
En python.es posteé lo siguiente:
"Si tengo un modulo apps.py que tiene:
import debug
def programBegin():
debug.init()
Y si tengo un modulo debug.py que tiene:
DEBUG = 0
def init():
global DEBUG
DEBUG=1
if ( __name__ == "__main__") :
import apps
apps.programBegin()
print DEBUG
¿Porque al ejecutar como comando el modulo debug.py, me imprime 0? Mi no entender..."
La respuesta (por parte de Gabriel Genellina):
"La clave está en que al ejecutar debug.py directamente, se crean DOS
copias del MISMO modulo.
1) El script que estas ejecutando (debug.py) se carga como modulo
'__main__' (es decir, en sys.modules se inserta un nuevo item con
clave='__main__' y valor=el modulo debug.py).
2) Cuando apps ejecuta "import debug", Python se fija si el modulo ya esta
importado (mirando las claves de sys.modules) y como no lo encuentra, lo
lee de disco y lo inserta con clave='debug'
O sea que debug.py fue importado DOS veces. Cuando programBegin llama a
debug.init, lo que se modifica es el valor de la variable DEBUG que esta
en el modulo llamado "debug". Cuando haces el print estando dentro del
script principal (que coincide con debug.py) lo que estas imprimiendo es
la variable DEBUG que esta en el modulo llamado "__main__".
De paso, esta es justamente la razon por la que funciona la condicion:
if __name__ == "__main__":
que más de uno escribe sin tener ni idea de porqué se hace así."
"Si tengo un modulo apps.py que tiene:
import debug
def programBegin():
debug.init()
Y si tengo un modulo debug.py que tiene:
DEBUG = 0
def init():
global DEBUG
DEBUG=1
if ( __name__ == "__main__") :
import apps
apps.programBegin()
print DEBUG
¿Porque al ejecutar como comando el modulo debug.py, me imprime 0? Mi no entender..."
La respuesta (por parte de Gabriel Genellina):
"La clave está en que al ejecutar debug.py directamente, se crean DOS
copias del MISMO modulo.
1) El script que estas ejecutando (debug.py) se carga como modulo
'__main__' (es decir, en sys.modules se inserta un nuevo item con
clave='__main__' y valor=el modulo debug.py).
2) Cuando apps ejecuta "import debug", Python se fija si el modulo ya esta
importado (mirando las claves de sys.modules) y como no lo encuentra, lo
lee de disco y lo inserta con clave='debug'
O sea que debug.py fue importado DOS veces. Cuando programBegin llama a
debug.init, lo que se modifica es el valor de la variable DEBUG que esta
en el modulo llamado "debug". Cuando haces el print estando dentro del
script principal (que coincide con debug.py) lo que estas imprimiendo es
la variable DEBUG que esta en el modulo llamado "__main__".
De paso, esta es justamente la razon por la que funciona la condicion:
if __name__ == "__main__":
que más de uno escribe sin tener ni idea de porqué se hace así."
viernes, septiembre 21, 2007
lunes, septiembre 17, 2007
Via slashdot: Guido and Bruce Eckel Discuss Python 3000.
Debería ser de obligada lectura para los que curramos con python.
Bruce comenta que en Ruby también van a hacer ruptura hacia atrás, y que van a eliminar los 'perl-isms'. Muy interesante.... era una de las cosas que no me gustó de Ruby cuando le eché un vistazo.
Debería ser de obligada lectura para los que curramos con python.
Bruce comenta que en Ruby también van a hacer ruptura hacia atrás, y que van a eliminar los 'perl-isms'. Muy interesante.... era una de las cosas que no me gustó de Ruby cuando le eché un vistazo.
lunes, septiembre 10, 2007
viernes, septiembre 07, 2007
Column-oriented DBMS [wikipedia].
En la siguiente noticia de slashdot hablan sobre el tema: Are relational databases obsolete?
En la siguiente noticia de slashdot hablan sobre el tema: Are relational databases obsolete?
Un sitio al que voy a tener que echar un vistazo con calma: en High Scalability.
Via barrapunto: ¿Qué plataforma usan los sitios más populares?.
Via barrapunto: ¿Qué plataforma usan los sitios más populares?.
Suscribirse a:
Entradas (Atom)