scanf en python

Chema Cortés ch3m4 en ch3m4.org
Mar Sep 30 18:53:38 CEST 2003


Hola,

Estaba buscando algún método para fragmentar líneas de texto en campos 
de datos para su proceso. El formato de línea de los ficheros que 
utilizo puede variar bastante a menudo, así que quería algo que fuera 
simple de mantener en el futuro.

Como primera opción pensé en el rebanado de cadenas; pero buscando 
alguna optimización encontré el ejemplo que hay en la documentación del 
módulo re que simula el scanf. Lo he mejorado utilizando grupos de 
búsqueda (pongo el código abajo).

Antes de seguir, me preguntaba, por ser ésta una tarea bastante 
habitual, si alguien sabe de alguna solución elegante al problema.


Pongo el código en el que estoy trabajando (no está terminado). 
Convierte un fichero de campos de tamaño fijo en otro de campos 
delimitados por el carácter '|':

(-------- principio del fichero  ------------)
#!/usr/bin/python
# -*- coding: iso8859-15 -*-

import sys
import re
from datetime import date

fIn=file("nmcl0703.txt","r")
fOut=file("nmcl0703.txt"+".out","w")

#establezco el formato de línea del fichero de entrada
#(nombre_del_campo, longitud, tipo)
incommingRecord=(
     ("especialidad",6,int),
     ("",2,None),    #gap
     ("laboratorio",3,int),
     ("estado",2,str),
     ("grupo",5,str),
     ("",4,None),    #gap
     ("precio",8,float),
     ("",8,None),    #gap
     ("precio1",8,None),
     ("precio2",8,None),
     ("precio3",8,None),
     ("precio4",8,None),
     ("precio5",8,None),
     ("precio6",8,None),
     ("precio7",8,None),
     ("precio8",8,None),
     ("tipoaportacion",1,int),
     ("",4,None),    #gap
     ("nombrecomercial",42,str),
     ("",8,None),    #gap
     ("casacomercial",42,str)
)

outcommingRecord=[k for (k,n,t) in incommingRecord if t ]

#creo la expresión regular
#utilizo grupos de búsqueda con nombre (?P<nombre>pattern)
s=""
for k,n,t in incommingRecord:
     if k:
         s+="(?P<%s>.{%d})"%(k,n)
     else:
         s+=".{%d}"%n
s+="(?P<RESTO>.*)"
mk=re.compile(s)

for l in fIn:

     #generamos un diccionario con los campos
     r=mk.search(l).groupdict()

     #cambio de tipos
     for nom,tipo in [ (k,t) for (k,n,t) in incommingRecord if t in 
(int,float) ]:
         r[nom]=tipo(r[nom])

     #combinamos campos para la salida
     res="|".join([ str(r[k]) for k in outcommingRecord ])
     print >>fOut, res+"|"


#(------ fin del fichero ------)


-- 
Res publica non dominetur




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