examples - (Python) Contando líneas en un archivo enorme(> 10GB) lo más rápido posible
r plotly axis format (5)
Extendí la respuesta de gl y ejecuté su código usando el módulo de multiproceso Python para un conteo más rápido:
def blocks(f, cut, size=64*1024): # 65536
start, chunk =cut
iter=0
read_size=int(size)
_break =False
while not _break:
if _break: break
if f.tell()+size>start+chunk:
read_size=int(start+chunk- f.tell() )
_break=True
b = f.read(read_size)
iter +=1
if not b: break
yield b
def get_chunk_line_count(data):
fn, chunk_id, cut = data
start, chunk =cut
cnt =0
last_bl=None
with open(fn, "r") as f:
if 0:
f.seek(start)
bl = f.read(chunk)
cnt= bl.count(''/n'')
else:
f.seek(start)
for i, bl in enumerate(blocks(f,cut)):
cnt += bl.count(''/n'')
last_bl=bl
if not last_bl.endswith(''/n''):
cnt -=1
return cnt
....
pool = multiprocessing.Pool(processes=pool_size,
initializer=start_process,
)
pool_outputs = pool.map(get_chunk_line_count, inputs)
pool.close() # no more tasks
pool.join()
Esto mejorará el rendimiento de conteo 20 veces. Lo envolví en un script y se lo puse a Github.
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo obtener una cuenta de línea barata en Python? 37 respuestas
Tengo un script muy simple ahora que cuenta las líneas en un archivo de texto usando enumerate()
:
i = 0
f = open("C:/Users/guest/Desktop/file.log", "r")
for i, line in enumerate(f):
pass
print i + 1
f.close()
Esto toma alrededor de 3 minutos y medio para pasar por un archivo de registro de 15 GB con ~ 30 millones de líneas. Sería fantástico si pudiera obtener esto en menos de dos minutos, ya que estos son registros diarios y queremos hacer un análisis mensual, por lo que el código tendrá que procesar 30 registros de ~ 15 GB, más de una hora y media, posiblemente , y nos gustaría minimizar el tiempo y la carga de memoria en el servidor.
También me conformaría con un buen método de aproximación / estimación, pero debe ser de aproximadamente 4 sig.
¡Gracias!
Sé que es un poco injusto pero podrías hacer esto
int(subprocess.check_output("wc -l C://alarm.bat").split()[0])
Si estás en Windows Coreutils
Una solución rápida de 1 línea es:
sum((1 for i in open(file_path, ''rb'')))
Debería funcionar en archivos de tamaño arbitrario.
La respuesta de Ignacio es correcta, pero podría fallar si tiene un proceso de 32 bits.
Pero tal vez podría ser útil leer el archivo en bloque y luego contar los /n
caracteres en cada bloque.
def blocks(files, size=65536):
while True:
b = files.read(size)
if not b: break
yield b
with open("file", "r") as f:
print sum(bl.count("/n") for bl in blocks(f))
Hará tu trabajo.
Tenga en cuenta que no abro el archivo como binario, por lo que el /r/n
se convertirá a /n
, lo que hace que el conteo sea más confiable.
Para Python 3, y para hacerlo más robusto, para leer archivos con todo tipo de caracteres:
def blocks(files, size=65536):
while True:
b = files.read(size)
if not b: break
yield b
with open("file", "r",encoding="utf-8",errors=''ignore'') as f:
print (sum(bl.count("/n") for bl in blocks(f)))
mmap el archivo, y contar las nuevas líneas.