2009-11-27 18 views
7

Angenommen, Sie eine Datei öffnen, und kann eine seek() irgendwo in der Datei, wie Sie die aktuelle Datei Linie wissen?Wie bekomme ich die aktuelle offene Dateizeile in Python?

(Ich persönlich gelöst mit einer Ad-hoc-Dateiklasse, die die Suchposition auf die Zeile nach dem Scannen der Datei abbildet, aber ich wollte andere Hinweise sehen und diese Frage Stackoverflow hinzufügen, wie ich nicht finden konnte das Problem überall auf google)

+0

Ich stellte tatsächlich die Klasse irgendwo hier auf SO ... weiß nicht, wo. –

+1

Wenn Sie nach einem Byte-Offset suchen, gibt es keine Möglichkeit, die Zeile # zu kennen, ohne die Anzahl der Zeichen \ n vor dieser Position zu zählen. Was der effizienteste Weg mit einer Datei ist, bin ich mir nicht sicher .... Viel Glück! – gahooa

+0

ja. Vielleicht gibt es eine Bibliothek, die diesen Service anbietet. Ich habe es wie gesagt selbst implementiert, aber ich würde diese Aufgabe lieber an eine externe Bibliothek delegieren. –

Antwort

4

Hier ist, wie ich das Problem nähern würde, so viel Faulheit wie möglich mit:

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"))))) 

Für eine etwas weniger lesbar, aber viel mehr faul Ansatz verwenden enumerate und 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

coole Verwendung von itertools ... :) –

6

Wenn Sie suchen() verwenden, wird Python-Zeiger-Offsets zu verwenden, um die gewünschte Position in der Datei zu springen. Aber um die aktuelle Zeilennummer zu kennen, müssen Sie jedes Zeichen bis zu dieser Position untersuchen. So könnte man genauso gut verzichten seek() zugunsten von read():

ersetzen

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

mit

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

Vielleicht nicht Sie wollen f.read (num) verwenden, da Dies kann viel Speicher erfordern, wenn Num sehr groß ist. In diesem Fall könnten Sie einen Generator wie folgt verwenden:

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

Dies zu f.seek(num) mit dem zusätzlichen Nutzen Sie line_number des Gebens entspricht.

Verwandte Themen