2012-07-30 11 views
10

Mi pregunta está relacionada con la entrada de archivos en Python, usando open(). Tengo un archivo de texto mytext.txt con 3 líneas. Estoy tratando de hacer dos cosas con este archivo: imprimir las líneas e imprimir el número de líneas.bucle de python a través del archivo de entrada

He probado el siguiente código:

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
for line in input_file: 
    count_lines += 1 
print 'number of lines:', count_lines 

Resultado: imprime las 3 líneas correctamente, pero no se imprime "número de líneas: 0" (en lugar de 3)


encontré dos formas de resolverlo, y lo consigue para imprimir 3:

1) utilizo un bucle en lugar de dos

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
    count_lines += 1 
print 'number of lines:', count_lines 

2) después de que el primer bucle, defino archivo_entrada nuevo

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
input_file = open('mytext.txt', 'r') 
for line in input_file: 
    count_lines += 1 
print 'number of lines:', count_lines 

Para mí, parece que la definición input_file = ... es válido para un solo bucle, como si se elimina después de usarlo para un bucle Pero no entiendo por qué, probablemente todavía no esté 100% claro, cómo se trató variable = open(filename) en Python.

Por cierto, veo que en este caso es mejor usar solo un bucle. Sin embargo, creo que debo aclarar esta pregunta, ya que podría haber casos en los que pueda/deba hacer uso de ella.

+0

Si desea procesar líneas, por qué no usar 'readlines()' – tMC

+3

readlines harán que su máquina de movimiento de piernas y posiblemente bloquearse si de repente se lo utiliza con un archivo de gran tamaño. Por lo general, es mejor leer una línea a la vez. – user1277476

+0

también puede usar readline(), que lee una línea a la vez. O para evitar golpear/colisionar con líneas de lectura, use el parámetro de sugerencia de tamaño opcional: líneas de lectura (sugerencia de tamaño). Esto devolverá la cantidad de líneas enteras que pueden caber en un buffer de "sugerencia de tamaño". – ncultra

Respuesta

19

El identificador de archivo es un iterador. Después de iterar sobre el archivo, el puntero se colocará en EOF (fin del archivo) y el iterador levantará StopIteration, que sale del bucle. Si intenta usar un iterador para un archivo donde el puntero está en EOF, simplemente levantará StopIteration y saldrá: es por eso que cuenta cero en el segundo ciclo. Puede rebobinar el puntero de archivo con input_file.seek(0) sin volver a abrirlo.

Dicho esto, contar líneas en el mismo bucle es más eficiente de E/S; de lo contrario, debe leer todo el archivo del disco una segunda vez para contar las líneas. Este es un patrón muy común:

with open('filename.ext') as input_file: 
    for i, line in enumerate(input_file): 
     print line, 
print "{0} line(s) printed".format(i+1) 

En Python 2.5, el objeto de archivo ha sido equipado con __enter__ y __exit__ para abordar el with statement interface.Este es el azúcar sintáctica para algo como:

input_file = open('filename.txt') 
try: 
    for i, line in enumerate(input_file): 
     print line, 
finally: 
    input_file.close() 
print "{0} line(s) printed".format(i+1) 

Creo CPython cerrará identificadores de archivo cuando consiguen el recolector de basura, pero no estoy seguro de que esto es cierto para todas las implementaciones - En mi humilde opinión, es mejor la práctica de manera explícita cierra el recurso maneja.

+0

Ahora lo tengo. ¡Muchas gracias! Por cierto, supongo que no es algo específico de Python, pero probablemente la mayoría de los lenguajes funcionan así. Es bueno saberlo. Gracias de nuevo. –

5

¿Hay alguna razón no se podía utilizar el siguiente:

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
    count_lines += 1 
print 'number of lines:', count_lines 

Lo que devuelve abierta es un objeto de archivo. Los objetos de archivo realizan un seguimiento de su propia posición interna a medida que los recorre, por lo que para hacer lo que probó primero, debería rebobinarlo manualmente, no lo hará por sí solo.

+0

Como mencioné en mi publicación, sé que esta es una mejor manera. El motivo de mi publicación es que me gustaría entender el comportamiento de Python para el cual la primera opción no funciona. –

+0

Gracias por la explicación, ahora entiendo cómo funciona. –

2

Intente agregar un input_file.seek(0) entre los dos bucles. Esto rebobinará el archivo de nuevo al principio, por lo que puede recorrerlo de nuevo.

0

Reduzco la entrada de archivos del módulo que desea.

Here is the link

if __name__ == "__main__": 
for line in fileinput.input(): 
    if fileinput.isfirstline(): 
     print("current file: %s" % fileinput.filename()) 

    print("line number: %d, current file number: %d" % 
      (fileinput.lineno(), fileinput.filelineno())) 
Cuestiones relacionadas