[Python-es] Re: Mi primer "programa" en python, me queda funciones que no se muy bien cómo solventar

Gabriel Genellina gagsl-py2 en yahoo.com.ar
Mar Nov 6 06:03:31 CET 2007


En Mon, 05 Nov 2007 23:03:59 -0300, acido || cuatroxl.org  
<acido69 en gmail.com> escribió:

> Hola a todos, antes de nada explico lo que hace el programita:
>
> le paso un directorio y busca todos los archivos htm(podría buscar html o
> algo así pero será para la próxima versión) para hacer lo siguiente:
>      -convierte los nombres de los tags en minúsculas, si lo hay
>      -convierte a codigo html los caracteres tipo(á, é, í, ó....); esto  
> lo
> saca de un archivo configurable(config.txt)
>      -es recursivo en todas las carpetas hijas.

Como ejercicio para ir aprendiendo está bien, pero para la sustitución yo  
usaría la tabla que ya existe en htmlentitydefs por ejemplo. Siempre es  
mejor confiar en algo que ya está probado en lugar de inventarlo desde  
cero.

> El código ya funciona, pero me gustaría:
>        -que me reportara el error(en caso de haberlo) que se puede  
> presentar
> a la hora de sobrescribir el archivo
>        -me preocupa que exista archivos en utf8 y yo los guarde como  
> ansii,
> como detecto que codificación tiene???????

Habría que mirar los encabezados del archivo, y para eso tendrías que usar  
una clase que específicamente entienda HTML... y en ese caso casi todo el  
programa carece de sentido porque lo que estas haciendo ya deberia estar  
soportado...
Ahora, si se trata de "adivinar", podrias probar con Universal Encoding  
Detector: http://chardet.feedparser.org/ (hecho por el autor de un buen  
libro sobre Python, Mark Pilgrim: "Dive Into Python")

> def Mm(f):

Mm?????? f????? Acaso el gobierno ya lanzó un impuesto a las letras usadas  
en identificadores? ;)

>     coincidencias1=re.findall("[\n][^<]*[>]",f)
>     coincidencias2=re.findall("[<][^>]*[\n]",f)
>     coincidencias3=re.findall("[<].*[>]",f)

En general nunca es buena idea parsear html "a mano". Aunque quieras,  
usando expresiones regulares no vas a poder con todos los casos.

>     resultado=f
>     for i in coincidencias1:
>         busca=re.search(i,resultado)
>         if busca:
>             p1=busca.start()
>             p2=busca.end()
>             resultado1=resultado[:p1]
>             resultado2=resultado[p2:]
>             anadido=string.lower(f[p1:p2])
>             resultado=resultado1+anadido+resultado2

(Otra vez los nombres de 1 letra...  
http://es.wikipedia.org/wiki/Python#Filosof.C3.ADa )
La verdad no entiendo qué es lo que pretendías hacer acá... Porqué buscar  
dos veces? Es decir, si ya encontraste todas las apariciones con findall,  
porque el segundo search?
Además, la idea no es convertir los TAGS nada mas en minusculas? Esto no  
te convierte tambien los atributos y el contenido?

>     for i in coincidencias2:
           [mismo bloque repetido]
>     for i in coincidencias3:
           [mismo bloque repetido]

Suponiendo que el primer bloque estuviera bien escrito, en lugar de  
copiarlo 3 veces cambiando coincidencias1,2,3 podrias haberlo englobado en  
un bloque mas externo, así:

       for coincidencias in coincidencias1, coincidencias2, coincidencias3:
           for grupo in coincidencias:
              #...

>     return resultado
>def corrige(archivo, caracterValor):
>     flectura=open(archivo,'r')
>     contenido=flectura.read()
>     flectura.close()
>     contenido=Mm(contenido)
>     contenido=reemplaza(caracterValor, contenido)
>     #aquí guardas el nuevo
>         #si toddo ok devuelve true
>         #si falla algo devuelve false y para todo
>     fescritura=open(archivo, 'w')
>     fescritura.write(contenido);
>     fescritura.close

Faltan los (), sino no estas llamando a la funcion: fescritura.close()

>     #aquí siempre devuelve true, pero realmente no comprueba nada
>     return 1

No hace falta "comprobar" nada, si hubiera algun error en el close (que no  
estabas ejecutando) se dispara una excepcion. Si no haces nada especial,  
tu programa va a abortar en ese punto (y puede ser lo más recomendable)

Ademas no devuelve true, devuelve 1. El valor booleano del 1 es True, pero  
eso es otra cosa. True como tal es una instancia de la clase bool.

> def getCaracterValor(path='config.txt'):
>     salida=[]
>     flectura=open(os.path.join(path),'r')
os.path.join(path) es lo mismo que path... (?)
>     for i in flectura:
>         a = i.split('=')
>         a[1] = a[1][0:-1]
>         salida.append((a[0],a[1]))
>     flectura.close
Igual que el close de arriba.
>     return salida

> def getFiles(path):
       "Aca deberia haber una descripcion de esta funcion"
>     src =  os.path.realpath(path)
>     for i in os.listdir(path):

Uh... "i" como nombre de variable sólo se usa para el índice de un  
bucle... Yo acá usaría nombre_archivo por ejemplo. O apenas nombre. Pero  
no i a secas.

>         if os.path.isfile(os.path.join(path, i)):

En lugar de iterar a mano y discriminar si es un archivo o un directorio,  
podrias usar directamente os.walk y olvidarte de la recursion. Algo asi:
     for dirpath, dirs, archs in os.walk(path):
         for nombre in archs:
            ... lo de abajo

>             _extension=i.split('.')[-1]

Mejor os.path.splitext(nombre)[1] (ojo que incluye el punto).
Porqué el guión bajo? Se usa para nombres de *atributos* que uno quiere  
que sean privados, pero para variables locales no tiene mucho sentido.

>             if _extension == 'htm':
>                 if corrige(src+'\\'+i, getCaracterValor()):

Arriba usaste os.path.join asi que ya lo conocias... porque entonces aca  
estas concatenando a mano? Si usas la variante con os.walk, aca deberia  
decir os.path.join(dirpath, nombre). Y lo podrias guardar en una variable,  
por ejemplo, nombre_completo, para usarla tambien en los dos prints de  
abajo.

>                     print src+'\\'+i+'------------->OK'
>                 else:
>                     print src+'\\'+i+'------------->NO'
>         if os.path.isdir(os.path.join(path, i)):
>             getFiles(src+'\\'+i)

Usando os.walk, la recursion es automatica asi que estas dos lineas no van.

-- 
Gabriel Genellina



Más información sobre la lista de distribución Python-es