Cómo comprobar si hay EOF en Python?
Pregunta
¿Cómo puedo comprobar para EOF en Python? He encontrado un fallo en mi código donde no se añade el último bloque de texto después del separador a la lista de regreso. O tal vez hay una mejor manera de expresar esta función?
Aquí está mi código:
def get_text_blocks(filename):
text_blocks = []
text_block = StringIO.StringIO()
with open(filename, 'r') as f:
for line in f:
text_block.write(line)
print line
if line.startswith('-- -'):
text_blocks.append(text_block.getvalue())
text_block.close()
text_block = StringIO.StringIO()
return text_blocks
Solución
Puede que le resulte más fácil de solucionar esto usando itertools.groupby .
def get_text_blocks(filename):
import itertools
with open(filename,'r') as f:
groups = itertools.groupby(f, lambda line:line.startswith('-- -'))
return [''.join(lines) for is_separator, lines in groups if not is_separator]
Otra alternativa es utilizar una expresión regular para que coincida con los separadores:
def get_text_blocks(filename):
import re
seperator = re.compile('^-- -.*', re.M)
with open(filename,'r') as f:
return re.split(seperator, f.read())
Otros consejos
La condición de fin de archivo contiene lo antes de la expiración de la declaración for
- que parece la forma más sencilla para fijar minorly este código (se puede extraer text_block.getvalue()
al final si desea comprobar no está vacío antes de añadir que) .
Este es el problema estándar con emisores de buffers.
No detectar EOF - que es innecesario. Se escribe la última memoria intermedia.
def get_text_blocks(filename):
text_blocks = []
text_block = StringIO.StringIO()
with open(filename, 'r') as f:
for line in f:
text_block.write(line)
print line
if line.startswith('-- -'):
text_blocks.append(text_block.getvalue())
text_block.close()
text_block = StringIO.StringIO()
### At this moment, you are at EOF
if len(text_block) > 0:
text_blocks.append( text_block.getvalue() )
### Now your final block (if any) is appended.
return text_blocks
¿Por qué necesita StringIO aquí?
def get_text_blocks(filename):
text_blocks = [""]
with open(filename, 'r') as f:
for line in f:
if line.startswith('-- -'):
text_blocks.append(line)
else: text_blocks[-1] += line
return text_blocks
EDIT:. Fija la función, otras sugerencias podrían ser mejores, sólo quería escribir una función similar a la original
EDIT: asumió el archivo comienza con "- -", añadiendo cadena vacía a la lista, podrá "fijar" el IndexError o puede utilizar la siguiente:
def get_text_blocks(filename):
text_blocks = []
with open(filename, 'r') as f:
for line in f:
if line.startswith('-- -'):
text_blocks.append(line)
else:
if len(text_blocks) != 0:
text_blocks[-1] += line
return text_blocks
Pero ambas versiones se ven un poco feo para mí, la versión reg-ex es mucho más limpio.
Esta es una forma rápida de ver si tiene un archivo vacío:
if f.read(1) == '':
print "EOF"
f.close()