Como ha señalado @ajon, no creo que haya nada fundamentalmente malo con su código, excepto la sangría. Con la sangría arreglada, funciona para mí. Sin embargo, hay un par de oportunidades para mejorar.
1) En Python, la forma estándar de iterar sobre las cosas es mediante el uso de for
loop. Al usar un bucle for
, no necesita definir variables de contador de bucle y realizar un seguimiento de ellas usted mismo para iterar sobre cosas. En su lugar, escribe algo como esto
for line in lines:
print line
para recorrer todos los elementos en una lista de cadenas e imprimirlos.
2) En la mayoría de los casos, así es como se verán sus lazos for
. Sin embargo, hay situaciones en las que realmente desea realizar un seguimiento del recuento de bucles. Su caso es una situación así, porque no solo necesita esa línea sino también las siguientes tres, y por lo tanto necesita usar el contador para indexar (lst[i]
). Para eso hay enumerate()
, que devolverá una lista de elementos y cuyo índice puede buclear.
for i, line in enumerate(lines):
print i
print line
print lines[i+7]
Si se va a mantener un registro manual del contador del bucle como en el ejemplo, hay dos cosas:
3) Eso i = i+1
debe ser movido fuera de los if
y else
bloques. Lo estás haciendo en ambos casos, así que ponlo después del if/else
. En su caso el bloque else
entonces no hace nada más, y puede ser eliminada:
while i < 500:
if Lines[i] == searchquery:
f2.write(Lines[i])
f2.write(Lines[i+1])
f2.write(Lines[i+2])
i = i+1
4) Ahora, esto causará un IndexError
con los archivos de menos de 500 líneas. En lugar de codificar con dificultad una cuenta de bucle de 500, debe usar la longitud real de la secuencia sobre la que está iterando. len(lines)
le dará esa longitud. Pero en lugar de usar un bucle while
, use un bucle for
y range(len(lst))
para recorrer una lista del rango de cero a len(lst) - 1
.
for i in range(len(lst)):
print lst[i]
5)open()
se puede utilizar como un context manager que se encarga de cerrar archivos para usted. Los administradores de contexto son un concepto bastante avanzado, pero son bastante simples de usar si ya están provistos para usted. Al hacer algo como esto
with open('test.txt') as f:
f.write('foo')
se abrirá el archivo y accesible para usted como f
dentro de ese bloque with
. Después de salir del bloque, el archivo se cerrará automáticamente, por lo que no puede olvidarse de cerrar el archivo.
En su caso está abriendo dos archivos. Esto se puede hacer utilizando sólo dos with
declaraciones y anidarlas
with open('one.txt') as f1:
with open('two.txt') as f2:
f1.write('foo')
f2.write('bar')
o, en Python 2.7/3.x Python, anidando dos gestor de contexto en un solo with
declaración:
with open('one.txt') as f1, open('two.txt', 'a') as f2:
f1.write('foo')
f2.write('bar')
6) Según el sistema operativo en el que se creó el archivo, las terminaciones de línea son diferentes. En las plataformas tipo UNIX es \n
, Mac antes de OS X usa \r
, y Windows usa \r\n
. De modo que Lines[i] == searchquery
no coincidirá con los finales de línea de Mac o Windows. file.readline()
puede tratar con los tres, pero como mantiene las terminaciones de línea al final de la línea, la comparación fallará. Esto se resuelve mediante el uso de str.strip()
, que se tira de la cadena de todos los espacios en blanco al principio y al final, y comparar un patrón de búsqueda sin la línea final para que:
searchquery = 'am'
# ...
if line.strip() == searchquery:
# ...
(Leyendo el archivo usando file.read()
y usar str.splitlines()
sería otra alternativa.)
Pero, ya que ha mencionado la cadena de búsqueda en realidad aparece al principio de la línea, vamos a hacer eso, mediante el uso de str.startswith()
:
if line.startswith(searchquery):
# ...
7) La guía oficial de estilo para Python, PEP8, recomienda usar CamelCase
para las clases, lowercase_underscore
para casi todo lo demás (variables, funciones, atributos, métodos, módulos, paquetes). Por lo tanto, en lugar de Lines
, use lines
. Este es definitivamente un punto menor en comparación con los otros, pero aún vale la pena llegar desde el principio.
Por lo tanto, teniendo en cuenta todas las cosas que iba a escribir el código de la siguiente manera:
searchquery = 'am'
with open('Test.txt') as f1:
with open('Output.txt', 'a') as f2:
lines = f1.readlines()
for i, line in enumerate(lines):
if line.startswith(searchquery):
f2.write(line)
f2.write(lines[i + 1])
f2.write(lines[i + 2])
Como @TomK señaló, todo este código se supone que si los partidos cadena de búsqueda, hay por lo menos dos líneas siguiéndolo. Si no puede confiar en esa suposición, tratar con ese caso utilizando un bloque try...except
como lo sugirió @poorsod es el camino correcto.
En el segundo ejemplo, parece que su cuerpo de bucle no está sangrado ... ¿se trata de un error de copiar/pegar o de lo que realmente tiene? – Collin
Probablemente debería examinar la función 'enumerate' y' for x in iterable'. –
@Collin Tienes razón, el problema fue la sangría.¡Probablemente miré ese código durante dos horas y nunca me di cuenta! ¡Gracias! – Andreanna