¿Hay alguna alternativa al siguiente código?
startFromLine = 141978 # or whatever line I need to jump to
urlsfile = open(filename, "rb", 0)
linesCounter = 1
for line in urlsfile:
if linesCounter > startFromLine:
DoSomethingWithThisLine(line)
linesCounter += 1
Si estoy procesando un archivo de texto enorme (~15MB)
con líneas de longitud desconocida pero diferente, y necesito saltar a una línea en particular, ¿qué número sé de antemano? Me siento mal procesándolos uno por uno cuando sé que podría ignorar al menos la primera mitad del archivo. Buscando una solución más elegante si la hay.
python
text-files
usuario63503
fuente
fuente
Respuestas:
linecache :
fuente
No puede avanzar sin leer el archivo al menos una vez, ya que no sabe dónde están los saltos de línea. Podrías hacer algo como:
fuente
Realmente no tiene tantas opciones si las líneas son de diferente longitud ... lamentablemente necesita procesar los caracteres finales de línea para saber cuándo ha progresado a la siguiente línea.
Sin embargo, puede acelerar drásticamente esto Y reducir el uso de memoria cambiando el último parámetro a "abrir" a algo que no sea 0.
0 significa que la operación de lectura de archivos no tiene búfer, lo cual es muy lento y requiere mucho disco. 1 significa que el archivo está almacenado en búfer de línea, lo que sería una mejora. Cualquier cosa por encima de 1 (digamos 8k, es decir: 8096 o superior) lee fragmentos del archivo en la memoria. Aún puede acceder a él
for line in open(etc):
, pero Python solo va un poco a la vez, descartando cada fragmento almacenado en búfer después de su procesamiento.fuente
Probablemente me eche a perder la abundante ram, pero 15 M no es enorme. Leer en la memoria
readlines()
es lo que suelo hacer con archivos de este tamaño. Acceder a una línea después de eso es trivial.fuente
Me sorprende que nadie mencione a Islice
o si quieres el resto del archivo
o si quieres cualquier otra línea del archivo
fuente
Dado que no hay forma de determinar la longitud de todas las líneas sin leerlas, no tiene más remedio que recorrer todas las líneas antes de la línea de partida. Todo lo que puede hacer es hacer que se vea bien. Si el archivo es realmente grande, es posible que desee utilizar un enfoque basado en generador:
Nota: el índice es cero según este enfoque.
fuente
Si no desea leer todo el archivo en la memoria ... es posible que deba crear algún formato que no sea texto sin formato.
por supuesto, todo depende de lo que intente hacer y de la frecuencia con la que salte por el archivo.
Por ejemplo, si va a saltar a las líneas muchas veces en el mismo archivo y sabe que el archivo no cambia mientras trabaja con él, puede hacer esto:
Primero, pase por todo el archivo y registre el " seek-location "de algunos números de línea clave (por ejemplo, cada 1000 líneas),
luego , si quieres la línea 12005, salta a la posición 12000 (que has registrado), luego lee 5 líneas y sabrás que estás en la línea 12005 y así sucesivamente
fuente
Si conoce de antemano la posición en el archivo (en lugar del número de línea), puede usar file.seek () para ir a esa posición.
Editar : puede usar la función linecache.getline (nombre de archivo, lineno) , que devolverá el contenido de la línea lineno, pero solo después de leer todo el archivo en la memoria. Bueno si está accediendo aleatoriamente a líneas desde dentro del archivo (como Python podría querer hacer para imprimir un rastreo) pero no es bueno para un archivo de 15 MB.
fuente
¿Qué genera el archivo que desea procesar? Si es algo que está bajo su control, puede generar un índice (qué línea está en qué posición) en el momento en que se agrega el archivo. El archivo de índice puede tener un tamaño de línea fijo (con espacios rellenados o con 0 números rellenos) y definitivamente será más pequeño. Y así se puede leer y procesar rápidamente.
fuente
He tenido el mismo problema (necesito recuperar una línea específica de archivo enorme).
Seguramente, siempre puedo ejecutar todos los registros en el archivo y detenerlo cuando el contador sea igual a la línea de destino, pero no funciona de manera efectiva en el caso de que desee obtener un número plural de filas específicas. Eso provocó que se resolviera el problema principal: cómo manejar directamente al lugar de archivo necesario.
Descubrí la siguiente decisión: en primer lugar, completé el diccionario con la posición inicial de cada línea (la clave es el número de línea y el valor: longitud acumulada de las líneas anteriores).
en última instancia, función de objetivo:
t.seek (line_number): comando que ejecuta la poda del archivo hasta el inicio de la línea. Entonces, si confirma readline, obtendrá su línea objetivo.
Usando este enfoque, he ahorrado una parte importante de tiempo.
fuente
Puede usar mmap para encontrar el desplazamiento de las líneas. MMap parece ser la forma más rápida de procesar un archivo
ejemplo:
luego use f.seek (compensaciones) para moverse a la línea que necesita
fuente
¿Las líneas en sí contienen información de índice? Si el contenido de cada línea fuera algo así como "
<line index>:Data
", entonces elseek()
enfoque podría usarse para hacer una búsqueda binaria a través del archivo, incluso si la cantidad deData
es variable. Buscaría el punto medio del archivo, leería una línea, verificaría si su índice es mayor o menor que el que desea, etc.De lo contrario, lo mejor que puede hacer es simplemente
readlines()
. Si no desea leer todos los 15 MB, puede usar elsizehint
argumento para reemplazar al menos muchos correos electrónicosreadline()
con un número menor de llamadas areadlines()
.fuente
Si está tratando con un archivo de texto y está basado en un sistema Linux , puede usar los comandos de Linux.
Para mí, ¡esto funcionó bien!
fuente
Aquí hay un ejemplo en el que se usa 'readlines (sizehint)' para leer un fragmento de líneas a la vez. DNS señaló esa solución. Escribí este ejemplo porque los otros ejemplos aquí están orientados a una sola línea.
fuente
Ninguna de las respuestas es particularmente satisfactoria, por lo que aquí hay un pequeño fragmento para ayudar.
Uso de ejemplo:
Esto implica realizar muchas búsquedas de archivos, pero es útil para los casos en los que no puede caber todo el archivo en la memoria. Hace una lectura inicial para obtener las ubicaciones de las líneas (por lo que lee todo el archivo, pero no lo guarda todo en la memoria), y luego cada acceso realiza una búsqueda de archivo después del hecho.
Ofrezco el fragmento anterior bajo la licencia MIT o Apache a discreción del usuario.
fuente
Puede usar esta función para devolver la línea n:
fuente