Как использовать read next (), начиная с любой строки в python? - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь начать чтение какого-нибудь файла из строки 3, но не могу.

Я пытался использовать readlines() + порядковый номер строки, как показано ниже:

x = 2
f = open('urls.txt', "r+").readlines( )[x]
line = next(f)
print(line)

но я получаю такой результат:

Traceback (most recent call last):
  File "test.py", line 441, in <module>
    line = next(f)
TypeError: 'str' object is not an iterator

Я хотел бы иметь возможность установить любую строку в качестве переменной, и оттуда, все время, пока я использую next(), она переходит к следующей строке.

ВАЖНО: поскольку это новая функция, и весь мой код уже использует next(f), решение должно иметь возможность работать с ней.

Ответы [ 5 ]

0 голосов
/ 08 января 2019

Просто позвоните next(f) столько раз, сколько вам нужно. (Нет необходимости слишком усложнять это с помощью itertools, и не глотать весь файл с помощью readlines.)

lines_to_skip = 3

with open('urls.txt') as f:
    for _ in range(lines_to_skip):
        next(f)

    for line in f:
        print(line.strip())

Выход:

% cat urls.txt
url1
url2
url3
url4
url5

% python3 test.py
url4
url5
0 голосов
/ 07 января 2019

Следующий код позволит вам использовать итератор для печати первой строки:

In [1]: path = '<path to text file>'                                                           

In [2]: f = open(path, "r+")                                                    

In [3]: line = next(f)

In [4]: print(line)

Этот код позволит вам напечатать строки, начинающиеся с x th строки:

In [1]: path = '<path to text file>'

In [2]: x = 2

In [3]: f = iter(open(path, "r+").readlines()[x:])

In [4]: f = iter(f)                                                             

In [5]: line = next(f)

In [6]: print(line)

Редактировать: отредактировал решение на основе наблюдения @ Tomothy32.

0 голосов
/ 07 января 2019

Попробуйте это (использует itertools.islice):

from itertools import islice

f = open('urls.txt', 'r+')
start_at = 3
file_iterator = islice(f, start_at - 1, None)

# to demonstrate
while True:
    try:
        print(next(file_iterator), end='')
    except StopIteration:
        print('End of file!')
        break

f.close()

urls.txt

1
2
3
4
5

Выход:

3
4
5
End of file!

Это решение лучше, чем readlines, потому что оно не загружает весь файл в память, а загружает его только при необходимости. Это также не тратит время на повторение предыдущих строк, когда islice может сделать это, что делает его намного быстрее, чем ответ @ MadPhysicist.

Также рассмотрите возможность использования синтаксиса with, чтобы гарантировать закрытие файла:

with open('urls.txt', 'r+') as f:
    # do whatever
0 голосов
/ 07 января 2019

Строка, которую вы напечатали, возвращает строку:

open('urls.txt', "r+").readlines()[x]

open возвращает объект файла. Его метод readlines возвращает список строк. Индексирование с помощью [x] возвращает третью строку в файле в виде одной строки.

Первая проблема заключается в том, что вы открываете файл, не закрывая его. Во-вторых, ваш индекс не определяет диапазон строк до конца. Вот дополнительное улучшение:

with open('urls.txt', 'r+') as f:
    lines = f.readlines()[x:]

Теперь lines - это список всех строк, которые вы хотите. Но сначала вы читаете весь файл в память, а затем отбрасываете первые две строки. Кроме того, список является итеративным, а не итератором, поэтому для эффективного использования next в нем вам потребуется выполнить дополнительный шаг:

lines = iter(lines)

Если вы хотите использовать тот факт, что файл уже является довольно эффективным итератором, примените к нему next столько раз, сколько вам нужно, чтобы удалить ненужные строки:

with open('urls.txt', 'r+') as f:
    for _ in range(x):
        next(f)
    # now use the file
    print(next(f))

После цикла for любая операция чтения файла начинается с третьей строки, будь то next(f), f.readline() и т. Д.

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

for n, _ in enumerate(f):
    if n == x:
        break

или

for _ in zip(f, range(x)): pass

После запуска любого из этих циклов next(f) вернет x -ую строку.

0 голосов
/ 07 января 2019

Метод readlines возвращает список строк для строк. Поэтому, когда вы берете readlines()[2], вы получаете третью строку в виде строки. Вызов next для этой строки не имеет смысла, поэтому вы получите ошибку.

Самый простой способ сделать это - слайс список: readlines()[x:] дает список всего, начиная со строки x и далее. Тогда вы можете использовать этот список так, как вам нравится.

Если ваше сердце настроено на итератор, вы можете превратить список (или почти что угодно) в итератор с помощью встроенной функции iter. Тогда вы можете next, насколько вам понравится.

...