2009-11-27 21 views
7

Supongamos que abre un archivo y hace una búsqueda() en algún lugar del archivo, ¿cómo sabe la línea actual del archivo?¿Cómo obtener la línea actual de archivos abiertos en python?

(Yo personalmente resolví con una clase de archivo ad-hoc que asigna la posición de búsqueda a la línea después de escanear el archivo, pero quería ver otras sugerencias y agregar esta pregunta a stackoverflow, ya que no pude encontrar el problema en cualquier parte de Google)

+0

De hecho, publiqué la clase en algún lugar aquí SO ... no sé dónde. –

+1

Si busca una compensación de bytes, no hay forma de saber la línea sin contar los caracteres # de \ n encontrados antes de esa posición. En cuanto a cuál es la forma más eficiente de un archivo, no estoy seguro ... ¡Buena suerte! – gahooa

+0

sí. tal vez hay alguna biblioteca que hace este servicio. Lo implementé yo mismo como dije, pero preferiría delegar esta tarea a una biblioteca externa si es posible. –

Respuesta

4

Así es como me gustaría abordar el problema, utilizando tanto la pereza como sea posible:

from random import randint 
from itertools import takewhile, islice 

file = "/etc/passwd" 
f = open(file, "r") 

f.seek(randint(10,250)) 
pos = f.tell() 

print "pos=%d" % pos 

def countbytes(iterable): 
    bytes = 0 
    for item in iterable: 
     bytes += len(item) 
     yield bytes 

print 1+len(list(takewhile(lambda x: x <= pos, countbytes(open(file, "r"))))) 

Para un enfoque ligeramente menos legible, pero mucho más lento, utilice enumerate y dropwhile:

from random import randint 
from itertools import islice, dropwhile 

file = "/etc/passwd" 
f = open(file, "r") 

f.seek(randint(10,250)) 
pos = f.tell() 

print "pos=%d" % pos 

def countbytes(iterable): 
    bytes = 0 
    for item in iterable: 
     bytes += len(item) 
     yield bytes 

print list(
     islice(
      dropwhile(lambda x: x[1] <= pos, enumerate(countbytes(open(file, "r")))) 
      , 1))[0][0]+1 
+0

uso genial de itertools ... :) –

6

Cuando usa seek(), python puede usar desplazamientos de puntero para saltar a la posición deseada en el archivo. Pero para conocer el número de línea actual, debe examinar cada personaje hasta esa posición. Por lo que también podría abandonar seek() a favor de la lectura():

Reemplazar

f = open(filename, "r") 
f.seek(55) 

con

f = open(filename, "r") 
line=f.read(55).count('\n')+1 
print(line) 

Tal vez usted no desea utilizar f.read (num) ya esto puede requerir mucha memoria si num es muy grande. En ese caso, podría utilizar un generador de la siguiente manera:

import itertools 
import operator 
line_number=reduce(operator.add,(f.read(1)=='\n' for _ in itertools.repeat(None,num))) 
pos=f.tell() 

Esto es equivalente a f.seek(num) con la ventaja añadida de que le da line_number.

Cuestiones relacionadas