Прочитайте первые N строк файла в python


150

У нас есть большой файл необработанных данных, который мы хотели бы обрезать до указанного размера. Я имею опыт работы с .net c #, однако хотел бы сделать это на python, чтобы упростить вещи и из интереса.

Как бы я получить первые N строк текстового файла в Python? Повлияет ли используемая ОС на реализацию?


я могу дать в качестве аргумента командной строки
Nons

Ответы:


241

Python 2

with open("datafile") as myfile:
    head = [next(myfile) for x in xrange(N)]
print head

Python 3

with open("datafile") as myfile:
    head = [next(myfile) for x in range(N)]
print(head)

Вот еще один способ (оба Python 2 и 3)

from itertools import islice
with open("datafile") as myfile:
    head = list(islice(myfile, N))
print head

1
Спасибо, это действительно очень полезно. Какая разница между двумя? (с точки зрения производительности, необходимых библиотек, совместимости и т. д.)?
Рассел

1
Я ожидаю, что производительность будет похожей, возможно, первая будет немного быстрее. Но первый не будет работать, если файл не содержит хотя бы N строк. Лучше всего измерить производительность по сравнению с некоторыми типичными данными, с которыми вы будете ее использовать.
Джон Ла Рой

1
Оператор with работает на Python 2.6 и требует дополнительного оператора import на 2.5. Для версии 2.4 или более ранней вам нужно переписать код с помощью try ... кроме блока. Стилистически я предпочитаю первый вариант, хотя, как уже упоминалось, второй вариант более устойчив для коротких файлов.
Alasdair

1
islice, вероятно, быстрее, чем это реализовано в C.
Алиса Перселл,

22
Имейте в виду , что если файлы имеют меньше N строк это поднимет StopIteration исключение, вы должны обрабатывать
Илиан Илиев

19
N = 10
with open("file.txt", "a") as file:  # the a opens it in append mode
    for i in range(N):
        line = next(file).strip()
        print(line)

23
Я передергиваюсь всякий раз, когда вижу f = open("file")обработку без исключения, чтобы закрыть файл. Pythonic способ обработки файлов - с помощью менеджера контекста, то есть с помощью оператора with. Это описано в учебнике Python по вводу-выводу . "It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way."
Марк Микофски

1
Зачем открывать файл в режиме добавления?
AMC

13

Если вы хотите быстро прочитать первые строки и не заботитесь о производительности, вы можете использовать .readlines()метод, который возвращает объект списка, а затем разбивает список на части.

Например, для первых 5 строк:

with open("pathofmyfileandfileandname") as myfile:
    firstNlines=myfile.readlines()[0:5] #put here the interval you want

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

print firstNlines

Одним из преимуществ по сравнению с другими ответами является возможность легко выбирать диапазон строк, например, пропуская первые 10 [10:30]или последние 10 строк [:-10]или занимая только четные строки [::2].


2
Верхний ответ, вероятно, более эффективен, но этот работает как очарование для маленьких файлов.
Т.Чмелевский

2
Обратите внимание, что это на самом деле сначала считывает весь файл в список (myfile.readlines ()), а затем склеивает первые 5 его строк.
AbdealiJK

2
Этого следует избегать.
Anilbey

1
Я не вижу причин использовать это, это не намного проще, чем значительно более эффективные решения.
AMC

@AMC спасибо за отзыв, я использую его в консоли для исследования данных, когда мне нужно быстро просмотреть первые строки, это просто экономит мое время при написании кода.
GM

9

Что я делаю, так это для вызова N строк pandas. Я думаю, что производительность не самая лучшая, но, например, если N=1000:

import pandas as pd
yourfile = pd.read('path/to/your/file.csv',nrows=1000)

3
Лучше было бы использовать nrowsопцию, которая может быть установлена ​​в 1000, и весь файл не загружен. pandas.pydata.org/pandas-docs/stable/generated/… В общем, у pandas есть этот и другие методы экономии памяти для больших файлов.
philshem

Да ты прав. Я просто исправляю это. Извините за ошибку.
кроманьонец

1
Вы также можете добавить, sepчтобы определить разделитель столбцов (который не должен появляться в файлах, отличных от CSV)
philshem

1
@ Cro-Magnon Я не могу найти эту pandas.read()функцию в документации, знаете ли вы какую-либо информацию по этому вопросу?
AMC

6

Не существует конкретного метода для чтения количества строк, отображаемых объектом файла.

Я думаю, что самый простой способ будет следующим:

lines =[]
with open(file_name) as f:
    lines.extend(f.readline() for i in xrange(N))

Это то, что я на самом деле хотел. Хотя я хотел добавить каждую строку в список. Спасибо.
Артданил

4

Основано на ответе gnibbler, получившем наибольшее количество голосов (20 ноября 2009 г. в 0:27): этот класс добавляет метод head () и tail () к объекту файла.

class File(file):
    def head(self, lines_2find=1):
        self.seek(0)                            #Rewind file
        return [self.next() for x in xrange(lines_2find)]

    def tail(self, lines_2find=1):  
        self.seek(0, 2)                         #go to end of file
        bytes_in_file = self.tell()             
        lines_found, total_bytes_scanned = 0, 0
        while (lines_2find+1 > lines_found and
               bytes_in_file > total_bytes_scanned): 
            byte_block = min(1024, bytes_in_file-total_bytes_scanned)
            self.seek(-(byte_block+total_bytes_scanned), 2)
            total_bytes_scanned += byte_block
            lines_found += self.read(1024).count('\n')
        self.seek(-total_bytes_scanned, 2)
        line_list = list(self.readlines())
        return line_list[-lines_2find:]

Использование:

f = File('path/to/file', 'r')
f.head(3)
f.tail(3)

4

Два наиболее интуитивных способа сделать это:

  1. Итерации по файлу построчно и breakпосле Nстрок.

  2. Перебирайте файл построчно, используя next()метод Ntimes. (По сути, это просто другой синтаксис того, что делает верхний ответ.)

Вот код:

# Method 1:
with open("fileName", "r") as f:
    counter = 0
    for line in f:
        print line
        counter += 1
        if counter == N: break

# Method 2:
with open("fileName", "r") as f:
    for i in xrange(N):
        line = f.next()
        print line

Суть в том, что если вы не используете readlines()или не enumerateсохраняете весь файл в памяти, у вас есть много вариантов.


3

Самый удобный способ для себя:

LINE_COUNT = 3
print [s for (i, s) in enumerate(open('test.txt')) if i < LINE_COUNT]

Решение, основанное на понимании списка Функция open () поддерживает итерационный интерфейс. Enumerate () покрывает кортежи open () и return (index, item), затем мы проверяем, что мы находимся в допустимом диапазоне (если i <LINE_COUNT), а затем просто выводим результат.

Наслаждайся Питоном. ;)


Это кажется немного более сложной альтернативой [next(file) for _ in range(LINE_COUNT)].
AMC

3

Для первых 5 строк просто сделайте:

N=5
with open("data_file", "r") as file:
    for i in range(N):
       print file.next()

2

Если вы хотите что-то, что, очевидно, (без поиска эзотерических вещей в руководствах) работает без импорта и попробуйте / исключая и работает на достаточном диапазоне версий Python 2.x (от 2.2 до 2.6):

def headn(file_name, n):
    """Like *x head -N command"""
    result = []
    nlines = 0
    assert n >= 1
    for line in open(file_name):
        result.append(line)
        nlines += 1
        if nlines >= n:
            break
    return result

if __name__ == "__main__":
    import sys
    rval = headn(sys.argv[1], int(sys.argv[2]))
    print rval
    print len(rval)

2

Если у вас действительно большой файл, и предполагается, что вы хотите, чтобы вывод был массивом, использование np.genfromtxt остановит ваш компьютер. Это намного лучше в моем опыте:

def load_big_file(fname,maxrows):
'''only works for well-formed text file of space-separated doubles'''

rows = []  # unknown number of lines, so use list

with open(fname) as f:
    j=0        
    for line in f:
        if j==maxrows:
            break
        else:
            line = [float(s) for s in line.split()]
            rows.append(np.array(line, dtype = np.double))
            j+=1
return np.vstack(rows)  # convert list of vectors to array

Если у вас действительно большой файл и предполагается, что вы хотите, чтобы выходной массив был пустым массивом. Это довольно уникальный набор ограничений, я не вижу никаких преимуществ в этом по сравнению с альтернативами.
AMC

1

Начиная с Python 2.6, вы можете воспользоваться более сложными функциями в базовом предложении IO. Таким образом, ответ с наивысшим рейтингом можно переписать так:

    with open("datafile") as myfile:
       head = myfile.readlines(N)
    print head

(Вам не нужно беспокоиться о том, что ваш файл содержит менее N строк, поскольку не генерируется исключение StopIteration.)


25
Согласно документам N - это количество байтов для чтения, а не количество строк .
Марк Микофски

4
N - количество байтов!
ч.т.д.

5
Вот это да. Разговор о плохом именовании. Имя функции упоминает, linesно аргумент ссылается на bytes.
ArtOfWarfare

0

Это сработало для меня

f = open("history_export.csv", "r")
line= 5
for x in range(line):
    a = f.readline()
    print(a)

Почему бы не использовать менеджер контекста? В любом случае, я не вижу, как это улучшает многие существующие ответы.
AMC


0

fname = input("Enter file name: ")
num_lines = 0

with open(fname, 'r') as f: #lines count
    for line in f:
        num_lines += 1

num_lines_input = int (input("Enter line numbers: "))

if num_lines_input <= num_lines:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)

else:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)
        print("Don't have", num_lines_input, " lines print as much as you can")


print("Total lines in the text",num_lines)

-1
#!/usr/bin/python

import subprocess

p = subprocess.Popen(["tail", "-n 3", "passlist"], stdout=subprocess.PIPE)

output, err = p.communicate()

print  output

Этот метод работал для меня


Это на самом деле не решение Python.
AMC

Я даже не понимаю, что написано в вашем ответе. Пожалуйста, добавьте некоторые объяснения.
Алексей Мариниченко
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.