Прочитайте перші N рядків файлу в python


150

У нас є великий файл необроблених даних, який ми хотіли б обрізати до заданого розміру. Я досвідчений в .net c #, однак хотів би зробити це в python для спрощення речей та інтересу.

Як би я пішов про отримання перших N рядків текстового файлу в python? Чи матиме операційна система який-небудь вплив на впровадження?


чи можу я дати аргумент n як аргумент командного рядка
неділя

Відповіді:


240

Пітон 2

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

Пітон 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
Оператор з операцією працює на Python 2.6 і вимагає додаткової заяви про імпорт на 2.5. Для версії 2.4 або новішої версії вам потрібно буде переписати код за допомогою спробу ... крім блоку. Стилістично я віддаю перевагу першому варіанту, хоча, як згадувалося, другий є більш надійним для коротких файлів.
Alasdair

1
islice, ймовірно, швидше, оскільки він реалізований у C.
Еліс Перселл

22
Майте на увазі, що якщо файлів менше, ніж N рядків, це призведе до виключення StopIteration, з яким ви маєте працювати
Ilian Iliev

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")без винятку обробку для закриття файлу. Пітонічний спосіб обробки файлів - це за допомогою менеджера контексту, тобто використання оператора з. Це висвітлено у вхідному підручнику 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/… В цілому, панди мають цю та інші методи збереження пам'яті для великих файлів.
філшем

Так, ти маєш рацію. Я просто виправлюю це. Вибачте за помилку.
Кроманьйон

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

Це те, що я насправді мав намір. Хоча я хоч і додаю кожен рядок до списку. Дякую.
artdanil

4

На підставі відповіді, яка найбільше проголосувала ("20 листопада '09 о 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()методу Nраз. (Це, по суті, лише інший синтаксис для того, що робить головна відповідь.)

Ось код:

# 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 () підтримує інтерфейс ітерації. Перерахування () охоплює відкриті () та повертаються кортежі (індекс, елемент), потім ми перевіряємо, чи ми знаходимось у межах прийнятого діапазону (якщо я <LINE_COUNT), а потім просто надрукуємо результат.

Насолоджуйтесь Python. ;)


Це просто здається трохи складнішою альтернативою [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 - кількість байтів!
qed

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.