Я использую цикл for для чтения файла, но я хочу читать только определенные строки, скажем, строки № 26 и № 30. Есть ли встроенная функция для достижения этой цели?
enumerate(x)использует x.next, поэтому ему не нужен весь файл в памяти.
Алок Сингхал
3
Моя маленькая говядина с этим заключается в том, что А) Вы хотите использовать вместо пары «открыть / закрыть» и таким образом держать тело коротким, Б) Но тело не такое короткое. Звучит как компромисс между скоростью / пространством и тем, что ты Питон. Я не уверен, что будет лучшим решением.
Хэмиш Грубиджан
5
с переоценен, питон прекрасно обходился более 13 лет без него
Дэн Д.
38
@ Дэн Д. Электричество переоценено, человечество обходилось без него более 200 тысяч лет. ;-) 'with' делает его более безопасным, более читаемым и на одну строку короче.
Ромен Винсент
9
зачем использовать для цикла, я не думаю, что вы понимаете значение big file. Цикл займет годы, чтобы достичь индекса
Используйте fileobject.readlines()или for line in fileobjectкак быстрое решение для небольших файлов.
Используйте linecacheдля более элегантного решения, которое будет достаточно быстро для чтения многих файлов, возможно многократно.
Воспользуйтесь советом @ Alok и используйте егоenumerate() для файлов, которые могут быть очень большими и не помещаться в память. Обратите внимание, что использование этого метода может замедлиться, поскольку файл читается последовательно.
Ницца. Я только что посмотрел на источник linecacheмодуля, и похоже, что он читает весь файл в памяти. Таким образом, если произвольный доступ важнее, чем оптимизация размера, linecacheэто лучший метод.
Алок Сингхал
7
с помощью linecache.getlin ('some_file', 4) я получаю 4-ю строку, а не 5-ю.
Хуан
Интересный факт: если вы используете набор вместо списка во втором примере, вы получите время выполнения O (1). Посмотрите в списке O (n). Внутренние наборы представлены в виде хэшей, поэтому вы получаете время выполнения O (1). в этом примере не так уж и много, но если использовать большой список чисел и заботиться об эффективности, то подходы - это путь.
Радий
linecacheтеперь, похоже, работает только для исходных файлов Python
Пол Х
Вы также можете использовать linecache.getlines('/etc/passwd')[0:4]для чтения в первой, второй, третьей и четвертой строках.
Зы
30
Быстрый и компактный подход может быть:
def picklines(thefile, whatlines):return[x for i, x in enumerate(thefile)if i in whatlines]
он принимает любой открытый подобный файлу объект thefile(оставляя до вызывающей стороны, должен ли он быть открыт из файла диска, или через, например, сокет, или другой подобный файлу поток) и набор нулевых индексов строки whatlinesи возвращает список, с низким объемом памяти и разумной скоростью. Если количество возвращаемых строк огромно, вы можете предпочесть генератор:
def yieldlines(thefile, whatlines):return(x for i, x in enumerate(thefile)if i in whatlines)
что в основном полезно только для циклов - обратите внимание, что единственное отличие заключается в использовании круглых, а не квадратных скобок в returnвыражении, создании понимания списка и выражения генератора соответственно.
Далее отметим , что , несмотря на упоминание о «линии» и «файл» эти функции гораздо, гораздо более общий характер - они будут работать на любой итерацию, будь то открытый файл или любой другой, возвращая список (или генератор) элементов на основе их прогрессивных номеров предметов. Итак, я бы предложил использовать более подходящие общие имена ;-).
@ephemient, я не согласен - genexp читает гладко и отлично.
Алекс Мартелли
Отличное и элегантное решение, спасибо! Действительно, должны поддерживаться даже большие файлы с выражением генератора. Не может быть более элегантным, чем это, не так ли? :)
Самуэль Лампа
Хорошее решение, как это можно сравнить с предложением @AdamMatan? Решение Adam может быть быстрее, поскольку оно использует дополнительную информацию (номера строк монотонно увеличиваются), что может привести к ранней остановке. У меня есть файл 10 ГБ, который я не могу загрузить в память.
Маннаггия
2
@Mannaggia Это недостаточно подчеркнуто в этом ответе, но whatlinesдолжно быть set, потому что if i in whatlinesбудет выполняться быстрее с набором, а не (отсортированным) списком. Сначала я этого не заметил, а вместо этого разработал свое собственное уродливое решение с отсортированным списком (в котором мне не нужно было каждый раз сканировать список, а if i in whatlinesименно так), но разница в производительности была незначительной (с моими данными), и это Решение гораздо элегантнее.
Это читает весь файл в память. Вы также можете вызвать file.read (). Split ('\ n'), а затем использовать поиск по индексу массива, чтобы получить интересующую вас строку ...
slice Объект, обычно содержащий часть последовательности. Срез создается с использованием записи нижнего индекса, [] с двоеточиями между числами, когда их несколько, например, в variable_name [1: 3: 5]. Скобка (нижний индекс) использует внутренние фрагменты объектов (или в более старых версиях __getslice __ () и __setslice __ ()).
Хотя нотация среза в целом не применима непосредственно к итераторам, itertoolsпакет содержит функцию замены:
from itertools import islice
# print the 100th linewith open('the_file')as lines:for line in islice(lines,99,100):print line
# print each third line until 100with open('the_file')as lines:for line in islice(lines,0,100,3):print line
Дополнительным преимуществом функции является то, что она не читает итератор до конца. Таким образом, вы можете делать более сложные вещи:
with open('the_file')as lines:# print the first 100 linesfor line in islice(lines,100):print line
# then skip the next 5for line in islice(lines,5):pass# print the restfor line in lines:print line
И чтобы ответить на оригинальный вопрос:
# how to read lines #26 and #30In[365]: list(islice(xrange(1,100),25,30,4))Out[365]:[26,30]
Безусловно, лучший подход при работе с большими файлами. Моя программа перешла от потребления 8GB + почти к нулю. Трейдофф был использованием ЦП, который увеличился с ~ 15% до ~ 40%, но фактическая обработка файла была на 70% быстрее. Я возьму этот обмен весь день. Спасибо вам! 🎉🎉🎉
GollyJer
1
Это кажется самым питоническим для меня. Спасибо!
Ипетрик
10
Чтение файлов невероятно быстро. Чтение файла размером 100 МБ занимает менее 0,1 секунды (см. Мою статью « Чтение и запись файлов с помощью Python» ). Следовательно, вы должны прочитать его полностью, а затем работать с отдельными строками.
То, что делает большинство ответов здесь, не неправильно, а плохой стиль. Открытие файлов всегда должно быть сделано, withпоскольку это гарантирует, что файл снова закрыт.
Так что вы должны сделать это так:
with open("path/to/file.txt")as f:
lines = f.readlines()print(lines[26])# or whatever you want to do with this lineprint(lines[30])# or whatever you want to do with this line
Огромные файлы
Если у вас есть большой файл и потребление памяти вызывает беспокойство, вы можете обрабатывать его построчно:
with open("path/to/file.txt")as f:for i, line in enumerate(f):pass# process line i
IMO - это действительно плохой стиль, чтобы читать весь файл неизвестной длины, только чтобы получить первые 30 строк ... как насчет потребления памяти ... а что насчет бесконечных потоков?
возврат42
@ return42 Очень сильно зависит от приложения. Для многих совершенно нормально предположить, что текстовый файл имеет гораздо меньший размер, чем доступная память. Если у вас есть потенциально большие файлы, я отредактировал свой ответ.
Мартин Тома
спасибо за ваше добавление, которое совпадает с ответом alok . И извините, нет, я не думаю, что это зависит от приложения. ИМО всегда лучше не читать больше строк, чем нужно.
возврат42
7
Некоторые из них прекрасны, но это можно сделать гораздо проще:
start =0# some starting index
end =5000# some ending index
filename ='test.txt'# some file we want to usewith open(filename)as fh:
data = fin.readlines()[start:end]print(data)
При этом будет использоваться просто нарезка списка, он загружает весь файл, но большинство систем соответствующим образом минимизируют использование памяти, это быстрее, чем большинство методов, приведенных выше, и работает с моими файлами данных 10G +. Удачи!
Вы можете выполнить поиск (), который помещает вашу головку чтения в указанный байт в файле. Это не поможет вам, если вы точно не знаете, сколько байтов (символов) записано в файле перед строкой, которую вы хотите прочитать. Возможно, ваш файл строго отформатирован (каждая строка - это Х количество байтов?), Или вы можете сами посчитать количество символов (не забудьте включить невидимые символы, такие как разрывы строк), если вы действительно хотите повысить скорость.
В противном случае вам придется читать каждую строку до строки, которую вы хотите, в соответствии с одним из многих решений, уже предложенных здесь.
def getitems(iterable, items):
items = list(items)# get a list from any iterable and make our own copy# since we modify itif items:
items.sort()for n, v in enumerate(iterable):if n == items[0]:yield v
items.pop(0)ifnot items:breakprint list(getitems(open("/usr/share/dict/words"),[25,29]))# ['Abelson\n', 'Abernathy\n']# note that index 25 is the 26th item
Роджер, мой любимый парень! Это может быть полезно с заявлением.
Хэмиш Грубиджан
2
Я предпочитаю этот подход, потому что он более универсален, то есть вы можете использовать его в файле, в результате f.readlines(), на StringIOобъекте, что угодно:
def read_specific_lines(file, lines_to_read):"""file is any iterable; lines_to_read is an iterable containing int values"""
lines = set(lines_to_read)
last = max(lines)for n, line in enumerate(file):if n +1in lines:yield line
if n +1> last:return>>>with open(r'c:\temp\words.txt')as f:[s for s in read_specific_lines(f,[1,2,3,1000])]['A\n','a\n','aa\n','accordant\n']
def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
fp = open(filename,"r")
src = fp.readlines()
data =[(index, line)for index, line in enumerate(src)if index in lines]
fp.close()return data
# Usage below
filename ="C:\\Your\\Path\\And\\Filename.txt"for line in indexLines(filename):# using default list, specify your own list of lines otherwiseprint"Line: %s\nData: %s\n"%(line[0], line[1])
Файловые объекты имеют метод .readlines (), который выдаст вам список содержимого файла, по одной строке на элемент списка. После этого вы можете просто использовать обычные методы нарезки списка.
это неверный ответ. после того, как первый вызов readlines()итератора будет исчерпан, а второй вызов либо возвратит пустой список, либо выдаст ошибку (не могу вспомнить, какая именно)
Пол Х
1
Вы можете сделать это очень просто с помощью этого синтаксиса, который кто-то уже упоминал, но это, безусловно, самый простой способ сделать это:
Для печати определенных строк в текстовом файле. Создайте список "lines2print", а затем просто напечатайте, когда перечисление находится "в" списке lines2print. Чтобы избавиться от лишних '\ n', используйте line.strip () или line.strip ('\ n'). Мне просто нравится «понимание списка» и я стараюсь использовать, когда могу. Мне нравится метод «с» для чтения текстовых файлов, чтобы не оставлять файл открытым по любой причине.
lines2print =[26,30]# can be a big list and order doesn't matter.with open("filepath",'r')as fp:[print(x.strip())for ei,x in enumerate(fp)if ei in lines2print]
или, если список маленький, просто введите список как список в понимание.
with open("filepath",'r')as fp:[print(x.strip())for ei,x in enumerate(fp)if ei in[26,30]]
Для печати нужной строки. Для печати строки выше / ниже требуемой строки.
def dline(file,no,add_sub=0):
tf=open(file)for sno,line in enumerate(tf):if sno==no-1+add_sub:print(line)
tf.close()
выполнить ----> dline ("D: \ dummy.txt", 6) т.е. dline ("путь к файлу", номер_строки, если вы хотите, чтобы верхняя строка искомой строки давала 1 для нижнего -1, это необязательное значение по умолчанию будет быть взятым 0)
Если вы хотите прочитать определенные строки, такие как строка, начинающаяся после некоторой пороговой строки, вы можете использовать следующие коды:
file = open("files.txt","r")
lines = file.readlines() ## convert to list of lines
datas = lines[11:] ## raed the specific lines
это настолько же непитонно, насколько это возможно.
SilentGhost
Дает неверный результат, так как вы не можете использовать readline и readline, как это (каждый из них меняет текущую позицию чтения).
Я извиняюсь за то, что пропустил ОГРОМНУЮ ошибку в моем первом коде. Ошибка была исправлена, и текущий код должен работать как положено. Спасибо за указание на мою ошибку, Роджер Пейт.
Ответы:
Если файл для чтения большой, и вы не хотите читать весь файл в памяти сразу:
Обратите внимание, что
i == n-1
дляn
й строки.В Python 2.6 или более поздней версии:
источник
enumerate(x)
используетx.next
, поэтому ему не нужен весь файл в памяти.big file
. Цикл займет годы, чтобы достичь индексаБыстрый ответ:
или:
Существует более элегантное решение для извлечения многих строк: linecache (любезно предоставлено «python: как перейти к определенной строке в огромном текстовом файле?» , Предыдущий вопрос на stackoverflow.com).
Цитирование документации по Python, указанной выше:
Измените
4
желаемый номер строки, и вы на связи. Обратите внимание, что 4 принесет пятую строку, так как отсчет начинается с нуля.Если файл может быть очень большим и вызывать проблемы при чтении в память, было бы неплохо принять совет @ Alok и использовать enumerate () .
Заключить:
fileobject.readlines()
илиfor line in fileobject
как быстрое решение для небольших файлов.linecache
для более элегантного решения, которое будет достаточно быстро для чтения многих файлов, возможно многократно.enumerate()
для файлов, которые могут быть очень большими и не помещаться в память. Обратите внимание, что использование этого метода может замедлиться, поскольку файл читается последовательно.источник
linecache
модуля, и похоже, что он читает весь файл в памяти. Таким образом, если произвольный доступ важнее, чем оптимизация размера,linecache
это лучший метод.linecache
теперь, похоже, работает только для исходных файлов Pythonlinecache.getlines('/etc/passwd')[0:4]
для чтения в первой, второй, третьей и четвертой строках.Быстрый и компактный подход может быть:
он принимает любой открытый подобный файлу объект
thefile
(оставляя до вызывающей стороны, должен ли он быть открыт из файла диска, или через, например, сокет, или другой подобный файлу поток) и набор нулевых индексов строкиwhatlines
и возвращает список, с низким объемом памяти и разумной скоростью. Если количество возвращаемых строк огромно, вы можете предпочесть генератор:что в основном полезно только для циклов - обратите внимание, что единственное отличие заключается в использовании круглых, а не квадратных скобок в
return
выражении, создании понимания списка и выражения генератора соответственно.Далее отметим , что , несмотря на упоминание о «линии» и «файл» эти функции гораздо, гораздо более общий характер - они будут работать на любой итерацию, будь то открытый файл или любой другой, возвращая список (или генератор) элементов на основе их прогрессивных номеров предметов. Итак, я бы предложил использовать более подходящие общие имена ;-).
источник
whatlines
должно бытьset
, потому чтоif i in whatlines
будет выполняться быстрее с набором, а не (отсортированным) списком. Сначала я этого не заметил, а вместо этого разработал свое собственное уродливое решение с отсортированным списком (в котором мне не нужно было каждый раз сканировать список, аif i in whatlines
именно так), но разница в производительности была незначительной (с моими данными), и это Решение гораздо элегантнее.Ради предложения другого решения:
Я надеюсь, что это быстро и легко :)
источник
если вы хотите строку 7
источник
close()
файл при открытии его таким образом?Для полноты картины, вот еще один вариант.
Давайте начнем с определения из документации по Python :
Хотя нотация среза в целом не применима непосредственно к итераторам,
itertools
пакет содержит функцию замены:Дополнительным преимуществом функции является то, что она не читает итератор до конца. Таким образом, вы можете делать более сложные вещи:
И чтобы ответить на оригинальный вопрос:
источник
Чтение файлов невероятно быстро. Чтение файла размером 100 МБ занимает менее 0,1 секунды (см. Мою статью « Чтение и запись файлов с помощью Python» ). Следовательно, вы должны прочитать его полностью, а затем работать с отдельными строками.
То, что делает большинство ответов здесь, не неправильно, а плохой стиль. Открытие файлов всегда должно быть сделано,
with
поскольку это гарантирует, что файл снова закрыт.Так что вы должны сделать это так:
Огромные файлы
Если у вас есть большой файл и потребление памяти вызывает беспокойство, вы можете обрабатывать его построчно:
источник
Некоторые из них прекрасны, но это можно сделать гораздо проще:
При этом будет использоваться просто нарезка списка, он загружает весь файл, но большинство систем соответствующим образом минимизируют использование памяти, это быстрее, чем большинство методов, приведенных выше, и работает с моими файлами данных 10G +. Удачи!
источник
Вы можете выполнить поиск (), который помещает вашу головку чтения в указанный байт в файле. Это не поможет вам, если вы точно не знаете, сколько байтов (символов) записано в файле перед строкой, которую вы хотите прочитать. Возможно, ваш файл строго отформатирован (каждая строка - это Х количество байтов?), Или вы можете сами посчитать количество символов (не забудьте включить невидимые символы, такие как разрывы строк), если вы действительно хотите повысить скорость.
В противном случае вам придется читать каждую строку до строки, которую вы хотите, в соответствии с одним из многих решений, уже предложенных здесь.
источник
Если ваш большой текстовый файл
file
строго структурирован (то есть каждая строка имеет одинаковую длинуl
), вы можете использовать дляn
-ой строкиОтказ от ответственности Это работает только для файлов с одинаковой длиной!
источник
Как насчет этого:
источник
Если вы не возражаете против импорта, то fileinput делает именно то, что вам нужно (это вы можете прочитать номер текущей строки)
источник
источник
Я предпочитаю этот подход, потому что он более универсален, то есть вы можете использовать его в файле, в результате
f.readlines()
, наStringIO
объекте, что угодно:источник
Вот мои маленькие 2 цента, за что стоит;)
источник
Лучшее и незначительное изменение для ответа Алока Сингхала
источник
Файловые объекты имеют метод .readlines (), который выдаст вам список содержимого файла, по одной строке на элемент списка. После этого вы можете просто использовать обычные методы нарезки списка.
http://docs.python.org/library/stdtypes.html#file.readlines
источник
@OP, вы можете использовать перечислять
источник
Используя оператор with, он открывает файл, печатает строки 26 и 30, а затем закрывает файл. Просто!
источник
readlines()
итератора будет исчерпан, а второй вызов либо возвратит пустой список, либо выдаст ошибку (не могу вспомнить, какая именно)Вы можете сделать это очень просто с помощью этого синтаксиса, который кто-то уже упоминал, но это, безусловно, самый простой способ сделать это:
источник
Чтобы напечатать строку № 3,
Оригинальный автор: Фрэнк Хофманн
источник
Довольно быстро и точно.
Для печати определенных строк в текстовом файле. Создайте список "lines2print", а затем просто напечатайте, когда перечисление находится "в" списке lines2print. Чтобы избавиться от лишних '\ n', используйте line.strip () или line.strip ('\ n'). Мне просто нравится «понимание списка» и я стараюсь использовать, когда могу. Мне нравится метод «с» для чтения текстовых файлов, чтобы не оставлять файл открытым по любой причине.
или, если список маленький, просто введите список как список в понимание.
источник
Для печати нужной строки. Для печати строки выше / ниже требуемой строки.
выполнить ----> dline ("D: \ dummy.txt", 6) т.е. dline ("путь к файлу", номер_строки, если вы хотите, чтобы верхняя строка искомой строки давала 1 для нижнего -1, это необязательное значение по умолчанию будет быть взятым 0)
источник
Если вы хотите прочитать определенные строки, такие как строка, начинающаяся после некоторой пороговой строки, вы можете использовать следующие коды:
file = open("files.txt","r") lines = file.readlines() ## convert to list of lines datas = lines[11:] ## raed the specific lines
источник
источник
Я думаю, что это будет работать
источник