Jak odczytać plik linia po linii na liście?


2027

Jak czytać każdą linię pliku w Pythonie i przechowywać każdą linię jako element na liście?

Chcę czytać plik linia po linii i dołączać każdą linię na końcu listy.

Odpowiedzi:


2174
with open(filename) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 

206
Nie używaj file.readlines()w forpętli, wystarczy sam obiekt pliku:lines = [line.rstrip('\n') for line in file]
jfs

88
W przypadku pracy z Big Data użycie readlines()nie jest bardzo wydajne, ponieważ może spowodować błąd MemoryError . W takim przypadku lepiej jest iterować plik przy użyciu for line in f:i pracy z każdą linezmienną.
DarkCygnus

7
Sprawdziłem profil pamięci na różne sposoby podane w odpowiedziach, korzystając z opisanej tutaj procedury . Wykorzystanie pamięci jest znacznie lepsze, gdy każda linia jest odczytywana z pliku i przetwarzana, jak sugeruje tutaj @DevShark . Trzymanie wszystkich linii w obiekcie kolekcji nie jest dobrym pomysłem, jeśli pamięć jest ograniczeniem lub plik jest duży. Czas wykonania jest podobny w obu podejściach.
Tirtha R

6
Działa również .rstrip()nieco szybciej, jeśli usuwasz białe znaki z końców linii.
Gringo Suave,

Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta

1002

Zobacz Input i Ouput :

with open('filename') as f:
    lines = f.readlines()

lub z usunięciem znaku nowej linii:

with open('filename') as f:
    lines = [line.rstrip() for line in f]

12
Lepiej, użyj f.read().splitlines(), który usuwa nowe wiersze
Mark

Czy druga wersja jest for line in open(filename)bezpieczna? Czy plik zostanie automatycznie zamknięty?
becko

2
Najlepiej jest odczytywać plik po jednym wierszu na raz, zamiast czytać cały plik do pamięci jednocześnie. Nie działa to dobrze w przypadku dużych plików wejściowych. Zobacz poniżej odpowiedź Roberta.
Brad Hein

1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Jeśli piszę w ten sposób, jak mogę zamknąć plik po przeczytaniu?
Ramisa Anjum Aditi

2
Tak, do tego stopnia, że ​​robią to inni, chociaż nie jest to „najlepsza praktyka” do użycia openbez menedżera kontekstu (lub innego gwarantowanego sposobu zamknięcia go), to nie jest tak naprawdę jeden z tych przypadków - gdy obiekt nie ma już żadnych odniesień zostanie do niej wyrzucony śmieci, a plik zamknięty, co powinno nastąpić natychmiast po błędzie, czy nie, kiedy przetwarzanie listy zostanie zakończone.
Aaron Hall

579

Jest to bardziej wyraźne niż to konieczne, ale robi to, co chcesz.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)

18
Wolę tę odpowiedź, ponieważ nie wymaga załadowania całego pliku do pamięci (w tym przypadku nadal jest dołączana array, ale mogą istnieć inne okoliczności). Z pewnością w przypadku dużych plików takie podejście może złagodzić problemy.
JohannesB,

1
Dołączanie do tablicy jest wolne. Nie mogę wymyślić przypadku użycia, w którym jest to najlepsze rozwiązanie.
Elias Strehle

@Haccks, czy jest lepiej, ponieważ nie ładuje całego pliku do pamięci, czy jest więcej?
OrigamiEye

4
Uwaga: To rozwiązanie nie usuwa nowych linii.
AMC

1
To rozwiązanie ładuje cały plik do pamięci. Nie wiem, dlaczego ludzie myślą, że tak nie jest.
andrebrait

274

To da „tablicę” linii z pliku.

lines = tuple(open(filename, 'r'))

openzwraca plik, który można powtórzyć. Gdy iterujesz po pliku, otrzymujesz wiersze z tego pliku. tuplemoże pobrać iterator i utworzyć dla niego instancję krotki z iteratora, który mu podałeś. linesto krotka utworzona z linii pliku.


31
@MarshallFarrier Spróbuj lines = open(filename).read().split('\n')zamiast tego.
Noctis Skytower

16
czy to zamyka plik?
Vanuan

5
@ Vanuan Ponieważ po uruchomieniu linii nie ma już odwołania do pliku, destruktor powinien automatycznie zamknąć plik.
Noctis Skytower

30
@NoctisSkytower Uważam, że lines = open(filename).read().splitlines()jest trochę czystszy i uważam, że lepiej obsługuje zakończenia linii DOS.
jaynp

8
@ mklement0 Zakładając, że plik ma 1000 linii, listzajmuje około 13,22% więcej miejsca niż a tuple. Wyniki pochodzą z from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Utworzenie tuplezajmuje około 4,17% więcej czasu niż utworzenie list(z odchyleniem standardowym 0,16%). Wyniki pochodzą z uruchomienia from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30 razy. Moje rozwiązanie preferuje przestrzeń nad prędkością, gdy potrzeba zmienności jest nieznana.
Noctis Skytower

194

Jeśli chcesz \nuwzględnić:

with open(fname) as f:
    content = f.readlines()

Jeśli nie chcesz \nuwzględniać:

with open(fname) as f:
    content = f.read().splitlines()

168

Zgodnie z Python's Methods of File Objects , najprostszym sposobem konwersji pliku tekstowego na plik listjest:

with open('file.txt') as f:
    my_list = list(f)

Jeśli potrzebujesz tylko iterować linie wiersza pliku tekstowego, możesz użyć:

with open('file.txt') as f:
    for line in f:
       ...

Stara odpowiedź:

Korzystanie withi readlines():

with open('file.txt') as f:
    lines = f.readlines()

Jeśli nie zależy ci na zamknięciu pliku, ten jednowierszowy działa:

lines = open('file.txt').readlines()

Tradycyjny sposób:

f = open('file.txt') # Open file on read mode
lines = f.read().split("\n") # Create a list containing all lines
f.close() # Close file

149

Możesz po prostu wykonać następujące czynności, jak sugerowano:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Zauważ, że to podejście ma 2 wady:

1) Wszystkie linie zapisujesz w pamięci. W ogólnym przypadku jest to bardzo zły pomysł. Plik może być bardzo duży i może zabraknąć pamięci. Nawet jeśli nie jest duży, to po prostu strata pamięci.

2) Nie pozwala to na przetwarzanie każdej linii podczas ich czytania. Więc jeśli przetworzysz swoje linie po tym, nie będzie to wydajne (wymaga dwóch przejść zamiast jednego).

Lepszym podejściem do ogólnego przypadku byłoby:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Gdzie definiujesz swoją funkcję procesu w dowolny sposób. Na przykład:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(Wdrożenie Supermanklasy jest dla ciebie ćwiczeniem).

Będzie to działało ładnie dla każdego rozmiaru pliku i przejrzysz plik w ciągu zaledwie 1 przejścia. Tak zwykle działają ogólne parsery.


5
Właśnie tego potrzebowałem - i dziękuję za wyjaśnienie wad. Jako początkujący w Pythonie, niesamowite jest zrozumienie, dlaczego rozwiązanie jest rozwiązaniem. Twoje zdrowie!
Ephexx

5
Pomyśl trochę Corey. Czy naprawdę chcesz, aby Twój komputer czytał każdą linię, nie robiąc nic z tymi liniami? Z pewnością zdajesz sobie sprawę, że zawsze musisz je przetwarzać w taki czy inny sposób.
DevShark,

5
Zawsze musisz coś zrobić z liniami. Może to być tak proste, jak wydrukowanie linii lub ich policzenie. Nie ma sensu, aby proces czytał wiersze w pamięci, ale nic z tym nie robił.
DevShark

2
Zawsze musisz coś z nimi zrobić. Myślę, że próbujesz zrobić to, że możesz chcieć zastosować funkcję do wszystkich z nich naraz, zamiast pojedynczo. Tak się czasem dzieje. Ale jest to bardzo nieefektywne z punktu widzenia pamięci i uniemożliwia czytanie plików, jeśli jego powierzchnia jest większa niż ram. Dlatego typowe ogólne parsery działają w sposób, który opisałem.
DevShark

2
@PierreOcinom, który jest poprawny. Ponieważ plik jest otwarty w trybie tylko do odczytu, nie można zmodyfikować oryginalnego pliku za pomocą powyższego kodu. Aby otworzyć plik do odczytu i zapisu, użyjopen('file_path', 'r+')
DevShark

62

Dane do listy

Załóżmy, że mamy plik tekstowy z naszymi danymi, jak w poniższych wierszach,

Treść pliku tekstowego:

line 1
line 2
line 3
  • Otwórz cmd w tym samym katalogu (kliknij prawym przyciskiem myszy i wybierz cmd lub PowerShell)
  • Uruchom pythoniw interprecie napisz:

Skrypt Pythona:

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.strip() for l in file]
>>> x
['line 1','line 2','line 3']

Za pomocą append:

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

Lub:

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

Lub:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

Lub:

>>> y = [x.rstrip() for x in open("my_file.txt")]
>>> y
['line 1','line 2','line 3']


with open('testodiprova.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
  print(file)

with open('testodiprova.txt', 'r', encoding='utf-8') as file:
  file = file.readlines()
  print(file)

jest encoding="utf-8"wymagane?
Mausy5043

@ Mausy5043 nie, ale kiedy czytasz plik tekstowy, możesz mieć dziwny znak (zwłaszcza w języku włoskim)
Giovanni G. PY

1
read().splitlines()jest dostarczany przez Python: jest po prostu readlines()(co jest prawdopodobnie szybsze, ponieważ jest mniej marnotrawne).
Eric O Lebigot,

43

Aby odczytać plik na liście, musisz wykonać trzy czynności:

  • Otwórz plik
  • Przeczytaj plik
  • Zapisz zawartość jako listę

Na szczęście w Pythonie bardzo łatwo jest wykonywać te czynności, dlatego najkrótszym sposobem na odczyt pliku na listę jest:

lst = list(open(filename))

Dodam jednak więcej wyjaśnień.

Otwieranie pliku

Zakładam, że chcesz otworzyć konkretny plik i nie zajmujesz się bezpośrednio uchwytem pliku (lub uchwytem podobnym do pliku). Najczęściej używaną funkcją do otwierania pliku w Pythonie jest openpotrzeba jednego argumentu obowiązkowego i dwóch opcjonalnych w Pythonie 2.7:

  • Nazwa pliku
  • Tryb
  • Buforowanie (zignoruję ten argument w tej odpowiedzi)

Nazwa pliku powinna być ciągiem reprezentującym ścieżkę do pliku . Na przykład:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Pamiętaj, że należy określić rozszerzenie pliku. Jest to szczególnie ważne dla użytkowników systemu Windows z powodu rozszerzenia plików podoba .txtlub .docitp ukryte są domyślnie widziana w eksploratorze.

Drugim argumentem jest modetor : domyślnie oznacza to „tylko do odczytu”. Właśnie tego potrzebujesz w swoim przypadku.

Ale jeśli naprawdę chcesz utworzyć plik i / lub zapisać plik, potrzebujesz innego argumentu. Jest świetna odpowiedź, jeśli chcesz przegląd .

Aby odczytać plik, możesz go pominąć modelub przekazać:

open(filename)
open(filename, 'r')

Oba otworzą plik w trybie tylko do odczytu. Jeśli chcesz czytać w pliku binarnym w systemie Windows, musisz użyć trybu rb:

open(filename, 'rb')

Na innych platformach 'b'(tryb binarny) jest po prostu ignorowany.


Teraz, gdy pokazałem, jak openplik, porozmawiajmy o tym, że zawsze musiszclose go ponownie. W przeciwnym razie zachowa otwarty uchwyt pliku do pliku, dopóki proces się nie zakończy (lub Python zniszczy uchwyt pliku).

Chociaż możesz użyć:

f = open(filename)
# ... do stuff with f
f.close()

To nie zamknie pliku, gdy coś pomiędzy openi closezgłasza wyjątek. Można tego uniknąć, używając a tryi finally:

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Jednak Python zapewnia menedżerom kontekście, że mają składnię ładniejszej (ale za opento prawie identyczne do tryi finallypowyżej):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

Ostatnie podejście jest zalecanym podejściem do otwarcia pliku w Pythonie!

Czytanie pliku

Ok, otworzyłeś plik, a teraz jak go odczytać?

openFunkcja zwraca fileobiekt i obsługuje protokół iteracji pytony. Każda iteracja da ci linię:

with open(filename) as f:
    for line in f:
        print(line)

Spowoduje to wydrukowanie każdej linii pliku. Zauważ jednak, że każda linia będzie zawierała znak nowej linii \nna końcu (możesz chcieć sprawdzić, czy Twój Python jest zbudowany z uniwersalną obsługą nowej linii - w przeciwnym razie możesz mieć \r\nna Windowsie lub \rMacu jako nowe linie). Jeśli nie chcesz, możesz po prostu usunąć ostatni znak (lub dwa ostatnie znaki w systemie Windows):

with open(filename) as f:
    for line in f:
        print(line[:-1])

Ale ostatnia linia niekoniecznie ma końcową nową linię, więc nie należy jej używać. Można sprawdzić, czy kończy się on znakiem nowej linii, a jeśli tak, usuń go:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Ale może po prostu usunąć wszystkie spacje (w tym \ncharakterze) od końca łańcucha , to również usunąć wszystkie inne spływu spacje, więc trzeba być ostrożnym, jeśli są ważne:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Jednak jeśli linie kończą się na \r\n(Windows „newlines”), .rstrip()to również zajmie się \r!

Zapisz zawartość jako listę

Teraz, gdy wiesz, jak otworzyć plik i przeczytać go, czas zapisać zawartość na liście. Najprostszą opcją byłoby użycie listfunkcji:

with open(filename) as f:
    lst = list(f)

W przypadku, gdy chcesz usunąć końcowe znaki nowej linii, możesz zamiast tego użyć listy:

with open(filename) as f:
    lst = [line.rstrip() for line in f]

Lub jeszcze prościej: .readlines()metoda fileobiektu domyślnie zwraca a listz linii:

with open(filename) as f:
    lst = f.readlines()

Obejmuje to również końcowe znaki nowego wiersza, jeśli nie chcesz ich, zaleciłbym to [line.rstrip() for line in f]podejście, ponieważ pozwala to uniknąć przechowywania dwóch list zawierających wszystkie wiersze w pamięci.

Istnieje dodatkowa opcja uzyskania pożądanego wyniku, jednak jest on raczej „nieoptymalny”: readpełny plik w ciągu, a następnie dzielony na nowe wiersze:

with open(filename) as f:
    lst = f.read().split('\n')

lub:

with open(filename) as f:
    lst = f.read().splitlines()

Te automatycznie zajmują się końcowymi splitznakami nowej linii, ponieważ postać nie jest uwzględniona. Nie są one jednak idealne, ponieważ plik jest przechowywany jako ciąg znaków i jako lista wierszy w pamięci!

Podsumowanie

  • Użyj tej opcji with open(...) as fpodczas otwierania plików, ponieważ nie musisz samodzielnie zamykać pliku, a plik jest zamykany, nawet jeśli zdarzy się jakiś wyjątek.
  • fileobiekty obsługują protokół iteracji, więc czytanie pliku wiersz po wierszu jest tak proste, jak for line in the_file_object:.
  • Zawsze przeglądaj dokumentację pod kątem dostępnych funkcji / klas. Przez większość czasu istnieje idealne dopasowanie do zadania lub co najmniej jeden lub dwa dobre. Oczywistym wyborem byłoby w tym przypadku, readlines()ale jeśli chcesz przetworzyć linie przed zapisaniem ich na liście, zaleciłbym proste zrozumienie listy.

Ostatnie podejście jest zalecanym podejściem do otwarcia pliku w Pythonie! Dlaczego więc to trwa? Czy zdecydowana większość ludzi nie rzuci okiem na kilka pierwszych linii odpowiedzi przed przejściem?
AMC

@AMC Nie zastanawiałem się nad tym, kiedy napisałem odpowiedź. Czy uważasz, że powinienem umieścić to na górze odpowiedzi?
MSeifert

Tak może być najlepiej. Zauważyłem też, że wspominasz o Pythonie 2, więc również można go zaktualizować.
AMC

Ach, pytanie było pierwotnie oznaczone python-2.x. Może sensowniej zaktualizować go bardziej ogólnie. Zobaczę, czy dojdę do tego następnym razem. Dziękuję za twoje sugestie. Bardzo mile widziane!
MSeifert

42

Czysty i pytonowy sposób odczytywania linii pliku na liście


Przede wszystkim powinieneś skupić się na otwieraniu pliku i czytaniu jego zawartości w wydajny i pythoniczny sposób. Oto przykład sposobu, w jaki osobiście NIE preferuję:

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

Zamiast tego wolę poniższą metodę otwierania plików zarówno do odczytu, jak i zapisu, ponieważ jest ona bardzo czysta i nie wymaga dodatkowego kroku zamykania pliku po zakończeniu korzystania z niego. W poniższym zestawieniu otwieramy plik do odczytu i przypisujemy go do zmiennej „infile”. Po zakończeniu działania kodu w tej instrukcji plik zostanie automatycznie zamknięty.

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Teraz musimy skupić się na wprowadzeniu tych danych do listy Python, ponieważ są iterowalne, wydajne i elastyczne. W twoim przypadku pożądanym celem jest przeniesienie każdej linii pliku tekstowego do osobnego elementu. Aby to osiągnąć, użyjemy metody splitlines () w następujący sposób:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Produkt końcowy:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Testowanie naszego kodu:

  • Zawartość pliku tekstowego:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • Wydrukuj wyciągi do celów testowych:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Dane wyjściowe (wyglądające inaczej ze względu na znaki Unicode):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasã fatã.

30

Wprowadzony w Pythonie 3.4, pathlibma naprawdę wygodną metodę czytania tekstu z plików, jak następuje:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

( splitlinesWywołanie jest tym, co zmienia go z ciągu zawierającego całą zawartość pliku w listę linii w pliku).

pathlibma wiele przydatnych udogodnień. read_textjest miły i zwięzły i nie musisz się martwić otwieraniem i zamykaniem pliku. Jeśli wszystko, co musisz zrobić z plikiem, to przeczytać go za jednym razem, to dobry wybór.


29

Oto jeszcze jedna opcja, korzystając ze zrozumień list plików;

lines = [line.rstrip() for line in open('file.txt')]

Powinno to być bardziej wydajne, ponieważ większość pracy jest wykonywana w interpreterie Pythona.


10
rstrip()potencjalnie usuwa wszystkie końcowe białe znaki, nie tylko \n; użyć .rstrip('\n').
mklement0

Nie gwarantuje to również, że plik zostanie zamknięty po odczytaniu we wszystkich implementacjach Pythona (chociaż w CPython, głównej implementacji Pythona, tak będzie).
Mark Amery

1
Powinno to być bardziej wydajne, ponieważ większość pracy jest wykonywana w interpreterie Pythona. Co to znaczy?
AMC

28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Teraz zmienna out to lista (tablica) tego, czego chcesz. Możesz albo:

for line in out:
    print (line)

Lub:

for line in f:
    print (line)

Otrzymasz te same wyniki.


27

Odczytywanie i zapisywanie plików tekstowych za pomocą Python 2 i Python 3; działa z Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

Rzeczy do zauważenia:

  • withjest tak zwanym menedżerem kontekstu . Zapewnia to, że otwarty plik jest ponownie zamykany.
  • Wszystkie rozwiązania tutaj, które po prostu produkują .strip()lub .rstrip()nie powiela się, linesponieważ usuwają również białą przestrzeń.

Typowe zakończenia plików

.txt

Bardziej zaawansowane zapisywanie / odczytywanie plików

W przypadku aplikacji ważne mogą być:

  • Wsparcie z innych języków programowania
  • Wydajność czytania / pisania
  • Kompaktowość (rozmiar pliku)

Zobacz także: Porównanie formatów serializacji danych

Jeśli szukasz sposobu na utworzenie plików konfiguracyjnych, możesz przeczytać mój krótki artykuł Pliki konfiguracyjne w Pythonie .


26

Inną opcją jest numpy.genfromtxtna przykład:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Spowoduje to utworzenie datatablicy NumPy z tyloma wierszami, ile jest w twoim pliku.


25

Jeśli chcesz odczytać plik z wiersza poleceń lub ze standardowego wejścia, możesz również użyć fileinputmodułu:

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Przekaż do niego pliki tak:

$ python reader.py textfile.txt 

Przeczytaj więcej tutaj: http://docs.python.org/2/library/fileinput.html


20

Najprostszy sposób to zrobić

Prostym sposobem jest:

  1. Przeczytaj cały plik jako ciąg
  2. Podziel ciąg po linii

W jednym wierszu dałoby to:

lines = open('C:/path/file.txt').read().splitlines()

Jest to jednak dość nieefektywny sposób, ponieważ przechowuje 2 wersje zawartości w pamięci (prawdopodobnie nie jest to duży problem w przypadku małych plików, ale nadal). [Dzięki Mark Amery].

Istnieją 2 łatwiejsze sposoby:

  1. Używanie pliku jako iteratora
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Jeśli używasz języka Python 3.4 lub nowszego, lepiej użyj pathlibścieżki do pliku, której możesz użyć do innych operacji w programie:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]

To jest złe podejście. Po pierwsze, dzwonienie .read().splitlines()nie jest w żaden sposób „prostsze” niż zwykłe dzwonienie .readlines(). Po drugie, jest nieefektywna pamięci; niepotrzebnie przechowujesz dwie wersje zawartości pliku (pojedynczy ciąg zwracany przez .read()i lista ciągów zwracanych przez splitlines()) jednocześnie w pamięci.
Mark Amery

@MarkAmery True. Dziękujemy za podkreślenie tego. Zaktualizowałem swoją odpowiedź.
Jean-Francois T.

14

Wystarczy użyć funkcji splitlines (). Oto przykład.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

W wyniku pojawi się lista linii.


Nieefektywna pamięć w porównaniu do używania .readlines() . To powoduje zapisanie dwóch kopii zawartości pliku na raz (jedna jako pojedynczy ogromny ciąg, druga jako lista linii).
Mark Amery

11

Jeśli chcesz mieć do czynienia z bardzo dużym / dużym plikiem i chcesz czytać szybciej (wyobraź sobie, że bierzesz udział w konkursie kodowania Topcoder / Hackerrank), możesz od razu odczytać znacznie większy fragment linii do bufora pamięci zamiast po prostu iteruj wiersz po wierszu na poziomie pliku.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)

co robi proces (linia)? Pojawia się błąd, że nie ma takiej zmiennej zdefiniowanej. Wydaje mi się, że coś wymaga importowania i próbowałem zaimportować proces wieloprocesowy. Przetwarzam, ale nie o to chodzi. Czy możesz prosić o opracowanie? Dzięki
Newskooler

1
process(line)to funkcja, którą musisz wdrożyć, aby przetwarzać dane. na przykład, zamiast tej linii, jeśli ją użyjesz print(line), wypisze każdą linię z bufora linii.
Khanal

f.readlines (rozmiar bufora) zwraca niezmienny bufor. jeśli chcesz bezpośrednio wczytać do bufora, musisz użyć funkcji readinto (). Będę dużo szybszy.
David Dehghan

7

Najłatwiejszym sposobem na to z dodatkowymi korzyściami są:

lines = list(open('filename'))

lub

lines = tuple(open('filename'))

lub

lines = set(open('filename'))

W takim przypadku setmusimy pamiętać, że nie mamy zachowanej kolejności linii i pozbywamy się zduplikowanych linii.

Poniżej dodałem ważny suplement z @MarkAmery :

Ponieważ nie wywołujesz .closeobiektu pliku ani nie używasz withinstrukcji, w niektórych implementacjach Pythona plik może nie zostać zamknięty po odczytaniu, a proces wycieknie z otwartego uchwytu pliku .

W CPython (normalna implementacja Pythona, z której korzysta większość osób), nie stanowi to problemu, ponieważ obiekt pliku zostanie natychmiast wyrzucony do pamięci, co spowoduje zamknięcie pliku, ale ogólnie uważa się za najlepszą praktykę robienia czegoś takiego :

with open('filename') as f: lines = list(f) 

aby upewnić się, że plik zostanie zamknięty niezależnie od używanej implementacji języka Python .


1
Ponieważ nie wywołujesz .closeobiektu pliku ani nie używasz withinstrukcji, w niektórych implementacjach Pythona plik może nie zostać zamknięty po odczytaniu, a proces wycieknie z otwartego uchwytu pliku. W CPython (normalnej implementacji Pythona, z której korzysta większość osób), nie stanowi to problemu, ponieważ obiekt pliku zostanie natychmiast wyrzucony do pamięci, co spowoduje zamknięcie pliku, ale ogólnie uważa się za najlepszą praktykę, aby zrobić coś takiego, with open('filename') as f: lines = list(f)aby zapewnić, że plik zostanie zamknięty niezależnie od używanej implementacji języka Python.
Mark Amery

Dziękujemy za świetny komentarz @ MarkAmery! Bardzo to doceniam.
simhumileco

1
@simhumileco Dlaczego najlepsze (poprawne) rozwiązanie wystarcza?
AMC

@AMC, ponieważ najpierw chciałem pokazać najprostsze sposoby i spójność rozumowania.
simhumileco

Poza tym mam nadzieję, że moja odpowiedź jest krótka i łatwa do odczytania.
simhumileco

4

Użyj tego:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

datajest typem ramki danych i używa wartości, aby uzyskać ndarray. Możesz także uzyskać listę za pomocą array.tolist().


pandas.read_csv()jest do odczytu danych CSV , w jaki sposób jest tutaj odpowiedni?
AMC

4

Zarys i podsumowanie

Za pomocą a filename, obsługując plik z Path(filename)obiektu lub bezpośrednio za pomocą open(filename) as f, wykonaj jedną z następujących czynności:

  • list(fileinput.input(filename))
  • za pomocą with path.open() as f, zadzwońf.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • iteruj nad fileinput.inputlub fi list.appendkażdą linią pojedynczo
  • przejść fdo list.extendmetody powiązanej
  • używać fw zrozumieniu listy

Poniżej wyjaśniam przypadek użycia każdego z nich.

Jak w Pythonie czytać plik wiersz po wierszu?

To doskonałe pytanie. Najpierw utwórzmy przykładowe dane:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

Obiekty plików są leniwymi iteratorami, więc po prostu iteruj po nich.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

Alternatywnie, jeśli masz wiele plików, użyj fileinput.inputinnego leniwego iteratora. Za pomocą tylko jednego pliku:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

lub w przypadku wielu plików przekaż mu listę nazw plików:

for line in fileinput.input([filename]*2): 
    line # process the line

Ponownie, fi fileinput.inputpowyżej oba są / return leniwymi iteratorami. Możesz użyć iteratora tylko jeden raz, więc aby dostarczyć funkcjonalny kod, unikając gadatliwości, użyję nieco bardziej zwięzłego fileinput.input(filename)skąd apropos stąd.

W Pythonie, jak odczytać plik wiersz po wierszu na liście?

Ach, ale z jakiegoś powodu chcesz go na liście? Unikałbym tego, jeśli to możliwe. Ale jeśli nalegasz ... po prostu przekazać wynik fileinput.input(filename)do list:

list(fileinput.input(filename))

Inną bezpośrednią odpowiedzią jest wywołanie f.readlines, które zwraca zawartość pliku (do opcjonalnej hintliczby znaków, aby w ten sposób podzielić je na wiele list).

Możesz dostać się do tego obiektu pliku na dwa sposoby. Jednym ze sposobów jest przekazanie nazwy pliku do openwbudowanego:

filename = 'filename'

with open(filename) as f:
    f.readlines()

lub używając nowego obiektu Path z pathlibmodułu (który bardzo mi się spodobał i z którego będę korzystać odtąd):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list zajmie się również iteratorem plików i zwróci listę - całkiem bezpośrednią metodę:

with path.open() as f:
    list(f)

Jeśli nie masz nic przeciwko odczytaniu całego tekstu do pamięci jako pojedynczego łańcucha przed podzieleniem go, możesz to zrobić jako jedno-liniowy z Pathobiektem i splitlines()metodą łańcuchową. Domyślnie splitlinesusuwa nowe linie:

path.read_text().splitlines()

Jeśli chcesz zachować nowe linie, podaj keepends=True:

path.read_text().splitlines(keepends=True)

Chcę czytać plik linia po linii i dołączać każdą linię na końcu listy.

Teraz jest to trochę głupie, aby o to poprosić, biorąc pod uwagę, że z łatwością pokazaliśmy efekt końcowy za pomocą kilku metod. Ale podczas tworzenia listy może być konieczne filtrowanie linii lub operowanie nimi, więc załóżmy tę prośbę.

Użycie list.appendumożliwiłoby filtrowanie lub obsługę każdej linii przed jej dodaniem:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

Korzystanie list.extendbyłoby nieco bardziej bezpośrednie i być może przydatne, jeśli masz wcześniej istniejącą listę:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

Lub bardziej idiomatycznie, zamiast tego moglibyśmy użyć zrozumienia listy, a także mapować i filtrować w nim, jeśli to pożądane:

[line for line in fileinput.input(filename)]

Lub nawet bardziej bezpośrednio, aby zamknąć okrąg, po prostu przekaż go do listy, aby utworzyć nową listę bezpośrednio, bez operowania na liniach:

list(fileinput.input(filename))

Wniosek

Widziałeś wiele sposobów umieszczania wierszy z pliku na liście, ale zalecam unikanie materializacji dużych ilości danych na listę i zamiast tego, jeśli to możliwe, używaj leniwej iteracji Pythona do przetwarzania danych.

To znaczy, wolę fileinput.inputlub with path.open() as f.


4

W przypadku, gdy w dokumencie są również puste wiersze, lubię czytać zawartość i przepuszczać ją, filteraby zapobiec pustym elementom łańcucha

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))

1
To nie jest mityczne, bądź ostrożny.
AMC

3

Możesz także użyć polecenia loadtxt w NumPy. To sprawdza mniej warunków niż genfromtxt, więc może być szybsze.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")

2

Lubię używać następujących. Natychmiastowe czytanie linii.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

Lub używając rozumienia listy:

contents = [line.strip() for line in open(filepath, 'r').readlines()]

2
Nie ma takiej potrzeby readlines(), co powoduje nawet karę pamięci. Możesz go po prostu usunąć, ponieważ iteracja po pliku (tekstowym) daje kolejno każdą linię.
Eric O Lebigot,

2
Należy użyć withinstrukcji do otwarcia (i niejawnego zamknięcia) pliku.
Aran-Fey

2

Wypróbowałbym jedną z poniższych metod. Przykładowy plik, którego używam, ma nazwę dummy.txt. Plik można znaleźć tutaj . Zakładam, że plik znajduje się w tym samym katalogu co kod (możesz zmienić, fpathaby podać prawidłową nazwę pliku i ścieżkę folderu).

W obu poniższych przykładach podana jest lista, której szukasz lst.

1.> Pierwsza metoda :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> W drugiej metodzie można użyć modułu csv.reader z biblioteki standardowej Python :

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

Możesz użyć jednej z dwóch metod. Czas potrzebny na stworzenie lstjest prawie równy w obu metodach.


1
Jaka jest zaleta drugiego podejścia? Po co wywoływać dodatkową bibliotekę, która dodaje w przypadkach krawędzi (separator i cudzysłowy)?
Charlie Harding

Po co jest delimiter=' 'argument?
AMC

2

Oto klasa biblioteki pomocniczej Python (3) , której używam do uproszczenia operacji we / wy pliku:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Następnie użyłbyś FileIO.linesfunkcji w następujący sposób:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Pamiętaj, że parametry mode( "r"domyślnie) i filter_fn( domyślnie sprawdza puste linie) są opcjonalne.

Można nawet usunąć read, writeoraz deletemetody i po prostu pozostawić FileIO.lines, a nawet przekształcić go w osobnej metody zwanej read_lines.


Czy lines = FileIO.lines(path)naprawdę jest wystarczająco prostsze niż with open(path) as f: lines = f.readlines()uzasadnienie istnienia tego pomocnika? Oszczędzasz 17 znaków na połączenie. (I przez większość czasu, ze względu na wydajność i pamięć, będziesz chciał zapętlić obiekt pliku bezpośrednio zamiast wczytywać jego linie do listy, więc nie będziesz nawet chciał tego często używać!) często jest fanem tworzenia małych funkcji narzędziowych, ale ten wydaje mi się, że po prostu niepotrzebnie tworzy nowy sposób pisania czegoś, co już jest krótkie i łatwe dzięki standardowej bibliotece.
Mark Amery

Oprócz tego, co powiedział @MarkAmery, po co używać do tego klasy?
AMC

1

Wersja wiersza poleceń

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Biegnij z:

python3 somefile.py input_file_name.txt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.