Mezclando archivos y loops
-
05-07-2019 - |
Pregunta
Estoy escribiendo un script que registra los errores de otro programa y reinicia el programa donde se detuvo cuando encuentra un error. Por cualquier motivo, los desarrolladores de este programa no consideraron necesario poner esta funcionalidad en su programa de forma predeterminada.
De todos modos, el programa toma un archivo de entrada, lo analiza y crea un archivo de salida. El archivo de entrada está en un formato específico:
UI - 26474845
TI - the title (can be any number of lines)
AB - the abstract (can also be any number of lines)
Cuando el programa emite un error, le brinda la información de referencia que necesita para rastrear el error, es decir, la interfaz de usuario, la sección (título o resumen) y el número de línea relativo al comienzo del título o resumen. Quiero registrar las oraciones ofensivas del archivo de entrada con una función que toma el número de referencia y el archivo, encuentra la oración y la registra. La mejor manera de pensar en hacerlo es avanzar en el archivo un número específico de veces (es decir, n veces, donde n es el número de línea relativo al comienzo de la sección). La forma en que parecía tener sentido hacer esto es:
i = 1
while i <= lineNumber:
print original.readline()
i += 1
No veo cómo esto haría que perdiera datos, pero Python cree que sí y dice ValueError: la mezcla de iteración y los métodos de lectura perderían datos
. ¿Alguien sabe cómo hacer esto correctamente?
Solución
Obtienes el ValueError porque tu código probablemente tenga para la línea en el original:
además de original.readline ()
. Una solución fácil que soluciona el problema sin hacer que su programa sea más lento o consuma más memoria está cambiando
for line in original:
...
a
while True:
line = original.readline()
if not line: break
...
Otros consejos
Suponiendo que solo necesita una línea, esto podría ser de ayuda
import itertools
def getline(fobj, line_no):
"Return a (1-based) line from a file object"
return itertools.islice(fobj, line_no-1, line_no).next() # 1-based!
>>> print getline(open("/etc/passwd", "r"), 4)
'adm:x:3:4:adm:/var/adm:/bin/false\n'
Es posible que desee detectar los errores de StopIteration (si el archivo tiene menos líneas).
Aquí hay una versión sin el patrón feo while True
y sin otros módulos:
for line in iter(original.readline, ''):
if …: # to the beginning of the title or abstract
for i in range(lineNumber):
print original.readline(),
break