Как получить текущую открытую строку файла в Python? - PullRequest
7 голосов
/ 27 ноября 2009

Предположим, вы открываете файл и выполняете поиск () где-нибудь в файле. Как узнать текущую строку файла?

(я лично решил с помощью специального класса файлов, который отображает позицию поиска на строку после сканирования файла, но я хотел увидеть другие подсказки и добавить этот вопрос в stackoverflow, так как не смог найти проблема в любом месте на Google)

Ответы [ 2 ]

6 голосов
/ 27 ноября 2009

Когда вы используете seek (), python получает возможность использовать смещение указателя для перехода к нужной позиции в файле. Но чтобы узнать текущий номер строки, вам нужно проверить каждый символ до этой позиции. Так что вы можете также отказаться от seek () в пользу read ():

Заменить

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

с

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

Возможно, вы не хотите использовать f.read (num), поскольку для этого может потребоваться много памяти, если num очень велико. В этом случае вы можете использовать генератор, подобный этому:

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

Это эквивалентно f.seek(num) с дополнительным преимуществом: line_number.

4 голосов
/ 27 ноября 2009

Вот как я бы подошел к проблеме, используя как можно больше лени:

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

Для чуть менее удобочитаемого, но гораздо более ленивого подхода используйте enumerate и 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
...