Как получить текущую строку открытого файла в python?

StackOverflow https://stackoverflow.com/questions/1809232

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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 и drop while :

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

Другие советы

Когда вы используете 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top