enumerate(x)używa x.next, więc nie potrzebuje całego pliku w pamięci.
Alok Singhal
3
Moja mała wołowina polega na tym, że A) chcesz używać zamiast pary otwarta / zamknięta, a tym samym utrzymywać ciało krótkie, B) Ale ciało nie jest tak krótkie. Brzmi jak kompromis między prędkością / przestrzenią a byciem Pythonem. Nie jestem pewien, jakie byłoby najlepsze rozwiązanie.
Hamish Grubijan,
5
z jest przereklamowany, python radził sobie dobrze bez niego przez ponad 13 lat
Dan D.
38
@Dan D. Elektryczność jest przereklamowana, bez niej ludzkość dobrze sobie radzi przez ponad 200 tysięcy lat. ;-) „with” czyni go bezpieczniejszym, bardziej czytelnym i krótszym o jedną linię.
Romain Vincent
9
dlaczego używać pętli, nie sądzę, że rozumiesz znaczenie big file. Pętla zajmie lata, aby dotrzeć do indeksu
Użyj fileobject.readlines()lub for line in fileobjectjako szybkiego rozwiązania dla małych plików.
Użyj linecachedo bardziej eleganckiego rozwiązania, które będzie dość szybkie do odczytu wielu plików, możliwe wielokrotnie.
Skorzystaj z porad @ Aloka i użyjenumerate() plików, które mogą być bardzo duże i nie zmieściłyby się w pamięci. Pamiętaj, że użycie tej metody może spowolnić, ponieważ plik jest odczytywany sekwencyjnie.
Miły. Właśnie spojrzałem na źródło linecachemodułu i wygląda na to, że czyta cały plik z pamięci. Tak więc, jeśli losowy dostęp jest ważniejszy niż optymalizacja rozmiaru, linecachejest najlepszą metodą.
Alok Singhal
7
z linecache.getlin ('some_file', 4) Dostaję czwartą linię, a nie piątą.
Juan
fajny fakt: jeśli użyjesz zestawu zamiast listy w drugim przykładzie, otrzymasz czas działania O (1). Wyszukiwanie na liście to O (n). Zestawy wewnętrzne są reprezentowane jako skróty i dlatego otrzymujesz czas działania O (1). w tym przykładzie nie jest to wielka sprawa, ale jeśli używasz dużej listy liczb i zależy Ci na wydajności, to zestawy są właściwą drogą.
rady
linecacheteraz wydaje się działać tylko dla plików źródłowych Pythona
Paul H
Możesz także użyć linecache.getlines('/etc/passwd')[0:4]do czytania pierwszego, drugiego, trzeciego i czwartego wiersza.
zyy
30
Szybkie i kompaktowe podejście mogłoby być:
def picklines(thefile, whatlines):return[x for i, x in enumerate(thefile)if i in whatlines]
akceptuje to dowolny otwarty obiekt podobny do pliku thefile(pozostawiając programowi wywołującemu, czy należy go otworzyć z pliku dyskowego, czy np. przez gniazdo lub inny strumień podobny do pliku) i zestaw wskaźników wiersza od zera whatlines, i zwraca lista, z małą powierzchnią pamięci i rozsądną prędkością. Jeśli liczba zwracanych wierszy jest ogromna, możesz preferować generator:
def yieldlines(thefile, whatlines):return(x for i, x in enumerate(thefile)if i in whatlines)
co w zasadzie jest dobre tylko do zapętlania - zwróć uwagę, że jedyna różnica wynika z użycia w returninstrukcji zaokrąglonych, a nie kwadratowych nawiasów , dzięki czemu możliwe jest zrozumienie listy i wyrażenie generatora.
Zwróć też uwagę, że pomimo wzmianki o „wierszach” i „pliku” funkcje te są znacznie, znacznie bardziej ogólne - będą działać na każdym iterowalnym, czy to otwartym pliku, czy innym, zwracając listę (lub generator) elementów na podstawie ich progresywnych numerów przedmiotów. Sugeruję więc stosowanie bardziej odpowiednio ogólnych nazw ;-).
@ephemient, nie zgadzam się - genexp czyta płynnie i idealnie.
Alex Martelli
Doskonałe i eleganckie rozwiązanie, dzięki! Rzeczywiście, nawet duże pliki powinny być obsługiwane z wyrażeniem generatora. Nie może być bardziej elegancki niż to, prawda? :)
Samuel Lampa
Ładne rozwiązanie, jak to się ma do proponowanego przez @AdamMatan? Rozwiązanie Adama może być szybsze, ponieważ wykorzystuje dodatkowe informacje (monotonicznie rosnące numery linii), które mogą prowadzić do wczesnego zatrzymania. Mam plik 10 GB, którego nie mogę załadować do pamięci.
Mannaggia
2
@Mannaggia Nie jest wystarczająco podkreślone w tej odpowiedzi, ale whatlinespowinno być set, ponieważ if i in whatlinesbędzie działać szybciej z zestawem niż (posortowaną) listą. Nie zauważyłem tego po raz pierwszy i zamiast tego opracowałem własne brzydkie rozwiązanie z posortowaną listą (gdzie nie musiałem skanować listy za każdym razem, podczas gdyif i in whatlines tylko to robi), ale różnica w wydajności była znikoma (z moimi danymi) i to rozwiązanie jest znacznie bardziej eleganckie.
Mam nadzieję, że jest to najbardziej optymalne rozwiązanie.
maniac_user
2
Odczytuje to cały plik do pamięci. Równie dobrze możesz wywołać file.read (). Split ('\ n'), a następnie użyć odnośników indeksu tablic, aby uzyskać linię zainteresowania ...
plasterek Obiekt zwykle zawierający część sekwencji. Wycinek jest tworzony za pomocą notacji indeksu dolnego [] z dwukropkami między liczbami, gdy podano kilka, na przykład w zmiennej_nazwa [1: 3: 5]. Notacja w nawiasach (indeks dolny) wykorzystuje obiekty wycinków wewnętrznie (lub w starszych wersjach __getslice __ () i __setslice __ ()).
Chociaż notacja wycinka nie ma bezpośredniego zastosowania do iteratorów, itertoolspakiet zawiera funkcję zastępowania:
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
Dodatkową zaletą tej funkcji jest to, że nie czyta iteratora do końca. Możesz więc robić bardziej złożone rzeczy:
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
Aby odpowiedzieć na pierwotne pytanie:
# how to read lines #26 and #30In[365]: list(islice(xrange(1,100),25,30,4))Out[365]:[26,30]
Zdecydowanie najlepsze podejście do pracy z dużymi plikami. Mój program przeszedł z konsumpcji 8 GB + na prawie nic. Kompromisem było zużycie procesora, które wzrosło z ~ 15% do ~ 40%, ale faktyczne przetwarzanie pliku było o 70% szybsze. Będę to kompromis przez cały dzień. Dzięki Ci! 🎉🎉🎉
GollyJer
1
Wydaje mi się to najbardziej pytoniczne. Dzięki!
ipetrik
10
Odczytywanie plików jest niesamowicie szybkie. Odczyt pliku 100 MB zajmuje mniej niż 0,1 sekundy (zobacz mój artykuł Odczytywanie i zapisywanie plików w Pythonie ). Dlatego powinieneś przeczytać go całkowicie, a następnie pracować z pojedynczymi wierszami.
Większość odpowiedzi tutaj nie jest zła, ale zły styl. Zawsze należy otwierać plikiwith ponieważ zapewnia to, że plik zostanie ponownie zamknięty.
Więc powinieneś to zrobić w ten sposób:
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
Ogromne pliki
Jeśli zdarzy ci się mieć ogromny plik i zużycie pamięci stanowi problem, możesz go przetworzyć wiersz po wierszu:
with open("path/to/file.txt")as f:for i, line in enumerate(f):pass# process line i
IMO to naprawdę zły styl, aby przeczytać cały plik o nieznanej długości, tylko po to, aby uzyskać pierwsze 30 wierszy .. co jest z zużyciem pamięci .. a co z niekończącymi się strumieniami?
return42
@ return42 To zależy bardzo od aplikacji. Dla wielu jest całkowicie w porządku założyć, że plik tekstowy ma znacznie mniejszy rozmiar niż dostępna pamięć. Jeśli zdarzy ci się mieć potencjalnie ogromne pliki, zredagowałem moją odpowiedź.
Martin Thoma,
dzięki za dodanie, które jest takie samo jak odpowiedź alok . I przepraszam nie, nie sądzę, że to zależy od aplikacji. IMO zawsze lepiej nie czytaj więcej linii niż potrzebujesz.
return42
7
Niektóre z nich są piękne, ale można to zrobić o wiele prościej:
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)
Wykorzysta to proste wycinanie list, ładuje cały plik, ale większość systemów odpowiednio zminimalizuje zużycie pamięci, jest szybsza niż większość metod podanych powyżej i działa na moich plikach danych 10G +. Powodzenia!
Możesz wykonać wywołanie seek (), które pozycjonuje twoją głowicę odczytu do określonego bajtu w pliku. To ci nie pomoże, chyba że dokładnie wiesz, ile bajtów (znaków) zapisano w pliku przed wierszem, który chcesz przeczytać. Być może twój plik jest ściśle sformatowany (każda linia ma liczbę X bajtów?) Lub możesz sam policzyć liczbę znaków (pamiętaj o dołączaniu niewidocznych znaków, takich jak podział linii), jeśli naprawdę chcesz przyspieszenia.
W przeciwnym razie musisz przeczytać każdą linię przed linią, której chcesz, zgodnie z jednym z wielu rozwiązań już tutaj zaproponowanych.
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
Roger, mój ulubiony facet! To może skorzystać z oświadczenia z.
Hamish Grubijan
2
Wolę to podejście, ponieważ jest bardziej ogólne, tzn. Możesz użyć go w pliku, w wyniku f.readlines(), na StringIOobiekcie, cokolwiek:
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])
Obiekty plików mają metodę .readlines (), która daje listę zawartości pliku, po jednej linii na element listy. Następnie możesz po prostu użyć normalnych technik dzielenia listy.
to nie jest poprawna odpowiedź. po pierwszym wezwaniu do readlines()iteratora wyczerpie się, a drugie wywołanie zwróci pustą listę lub wyrzuci błąd (nie pamiętam, które)
Paul H
1
Możesz to zrobić bardzo prosto, korzystając ze składni, o której ktoś już wspomniał, ale jest to zdecydowanie najłatwiejszy sposób:
Aby wydrukować określone wiersze w pliku tekstowym. Utwórz listę „lines2print”, a następnie po prostu wydrukuj, gdy wyliczenie jest „na” liście lines2print. Aby pozbyć się dodatkowych „\ n”, użyj line.strip () lub line.strip ('\ n'). Po prostu lubię „rozumienie listy” i staram się używać, kiedy mogę. Lubię metodę „with” do czytania plików tekstowych, aby zapobiec pozostawieniu pliku otwartego z jakiegokolwiek powodu.
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]
lub jeśli lista jest mała, po prostu wpisz listę jako listę do zrozumienia.
with open("filepath",'r')as fp:[print(x.strip())for ei,x in enumerate(fp)if ei in[26,30]]
Aby wydrukować żądaną linię. Aby wydrukować linię powyżej / poniżej wymaganej linii.
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()
wykonaj ----> dline („D: \ dummy.txt”, 6) tj. dline („ścieżka pliku”, numer_wiersza, jeśli chcesz, aby górna linia szukanej linii dawała 1 dla dolnej -1, jest to opcjonalna wartość domyślna będzie być zajęty 0)
Jeśli chcesz odczytać określone linie, takie jak linia rozpoczynająca się po pewnej linii progowej, możesz użyć następujących kodów,
file = open("files.txt","r")
lines = file.readlines() ## convert to list of lines
datas = lines[11:] ## raed the specific lines
Daje zły wynik, ponieważ nie można używać linii readline i readline w ten sposób (każda z nich zmienia bieżącą pozycję odczytu).
Przepraszam, że przeoczyłem OGROMNY błąd w moim pierwszym kodzie. Błąd został poprawiony i bieżący kod powinien działać zgodnie z oczekiwaniami. Dzięki za zwrócenie uwagi na mój błąd, Roger Pate.
Odpowiedzi:
Jeśli plik do odczytu jest duży i nie chcesz jednocześnie czytać całego pliku w pamięci:
Zauważ, że
i == n-1
dlan
linii th.W Pythonie 2.6 lub nowszym:
źródło
enumerate(x)
używax.next
, więc nie potrzebuje całego pliku w pamięci.big file
. Pętla zajmie lata, aby dotrzeć do indeksuSzybka odpowiedź:
lub:
Istnieje bardziej eleganckie rozwiązanie do wyodrębniania wielu wierszy: linecache (dzięki uprzejmości „python: jak przejść do konkretnej linii w ogromnym pliku tekstowym?” , Poprzednie pytanie stackoverflow.com).
Cytując powyższą dokumentację w języku Python:
Zmień
4
żądany numer linii i gotowe. Zauważ, że 4 przyniosłoby piątą linię, ponieważ liczba jest liczona od zera.Jeśli plik może być bardzo duży i powodować problemy podczas wczytywania do pamięci, dobrym pomysłem może być skorzystanie z porady @ Alok i użycie funkcji enumerate () .
Podsumowując:
fileobject.readlines()
lubfor line in fileobject
jako szybkiego rozwiązania dla małych plików.linecache
do bardziej eleganckiego rozwiązania, które będzie dość szybkie do odczytu wielu plików, możliwe wielokrotnie.enumerate()
plików, które mogą być bardzo duże i nie zmieściłyby się w pamięci. Pamiętaj, że użycie tej metody może spowolnić, ponieważ plik jest odczytywany sekwencyjnie.źródło
linecache
modułu i wygląda na to, że czyta cały plik z pamięci. Tak więc, jeśli losowy dostęp jest ważniejszy niż optymalizacja rozmiaru,linecache
jest najlepszą metodą.linecache
teraz wydaje się działać tylko dla plików źródłowych Pythonalinecache.getlines('/etc/passwd')[0:4]
do czytania pierwszego, drugiego, trzeciego i czwartego wiersza.Szybkie i kompaktowe podejście mogłoby być:
akceptuje to dowolny otwarty obiekt podobny do pliku
thefile
(pozostawiając programowi wywołującemu, czy należy go otworzyć z pliku dyskowego, czy np. przez gniazdo lub inny strumień podobny do pliku) i zestaw wskaźników wiersza od zerawhatlines
, i zwraca lista, z małą powierzchnią pamięci i rozsądną prędkością. Jeśli liczba zwracanych wierszy jest ogromna, możesz preferować generator:co w zasadzie jest dobre tylko do zapętlania - zwróć uwagę, że jedyna różnica wynika z użycia w
return
instrukcji zaokrąglonych, a nie kwadratowych nawiasów , dzięki czemu możliwe jest zrozumienie listy i wyrażenie generatora.Zwróć też uwagę, że pomimo wzmianki o „wierszach” i „pliku” funkcje te są znacznie, znacznie bardziej ogólne - będą działać na każdym iterowalnym, czy to otwartym pliku, czy innym, zwracając listę (lub generator) elementów na podstawie ich progresywnych numerów przedmiotów. Sugeruję więc stosowanie bardziej odpowiednio ogólnych nazw ;-).
źródło
whatlines
powinno byćset
, ponieważif i in whatlines
będzie działać szybciej z zestawem niż (posortowaną) listą. Nie zauważyłem tego po raz pierwszy i zamiast tego opracowałem własne brzydkie rozwiązanie z posortowaną listą (gdzie nie musiałem skanować listy za każdym razem, podczas gdyif i in whatlines
tylko to robi), ale różnica w wydajności była znikoma (z moimi danymi) i to rozwiązanie jest znacznie bardziej eleganckie.Aby zaoferować inne rozwiązanie:
Mam nadzieję, że to szybkie i łatwe :)
źródło
jeśli chcesz wiersz 7
źródło
close()
plik, otwierając go w ten sposób?Dla kompletności, oto jeszcze jedna opcja.
Zacznijmy od definicji z dokumentacji Pythona :
Chociaż notacja wycinka nie ma bezpośredniego zastosowania do iteratorów,
itertools
pakiet zawiera funkcję zastępowania:Dodatkową zaletą tej funkcji jest to, że nie czyta iteratora do końca. Możesz więc robić bardziej złożone rzeczy:
Aby odpowiedzieć na pierwotne pytanie:
źródło
Odczytywanie plików jest niesamowicie szybkie. Odczyt pliku 100 MB zajmuje mniej niż 0,1 sekundy (zobacz mój artykuł Odczytywanie i zapisywanie plików w Pythonie ). Dlatego powinieneś przeczytać go całkowicie, a następnie pracować z pojedynczymi wierszami.
Większość odpowiedzi tutaj nie jest zła, ale zły styl. Zawsze należy otwierać pliki
with
ponieważ zapewnia to, że plik zostanie ponownie zamknięty.Więc powinieneś to zrobić w ten sposób:
Ogromne pliki
Jeśli zdarzy ci się mieć ogromny plik i zużycie pamięci stanowi problem, możesz go przetworzyć wiersz po wierszu:
źródło
Niektóre z nich są piękne, ale można to zrobić o wiele prościej:
Wykorzysta to proste wycinanie list, ładuje cały plik, ale większość systemów odpowiednio zminimalizuje zużycie pamięci, jest szybsza niż większość metod podanych powyżej i działa na moich plikach danych 10G +. Powodzenia!
źródło
Możesz wykonać wywołanie seek (), które pozycjonuje twoją głowicę odczytu do określonego bajtu w pliku. To ci nie pomoże, chyba że dokładnie wiesz, ile bajtów (znaków) zapisano w pliku przed wierszem, który chcesz przeczytać. Być może twój plik jest ściśle sformatowany (każda linia ma liczbę X bajtów?) Lub możesz sam policzyć liczbę znaków (pamiętaj o dołączaniu niewidocznych znaków, takich jak podział linii), jeśli naprawdę chcesz przyspieszenia.
W przeciwnym razie musisz przeczytać każdą linię przed linią, której chcesz, zgodnie z jednym z wielu rozwiązań już tutaj zaproponowanych.
źródło
Jeśli twój duży plik tekstowy
file
ma ściśle dobrą strukturę (co oznacza, że każda linia ma tę samą długośćl
), możesz użyć dlan
-tego wierszaOświadczenie Działa to tylko w przypadku plików o tej samej długości!
źródło
Co powiesz na to:
źródło
Jeśli nie przeszkadza Ci importowanie, fileinput wykonuje dokładnie to, czego potrzebujesz (możesz odczytać numer bieżącej linii)
źródło
źródło
Wolę to podejście, ponieważ jest bardziej ogólne, tzn. Możesz użyć go w pliku, w wyniku
f.readlines()
, naStringIO
obiekcie, cokolwiek:źródło
Oto moje małe 2 centy, za ile są warte;)
źródło
Lepsza i drobna zmiana w odpowiedzi Aloka Singhala
źródło
Obiekty plików mają metodę .readlines (), która daje listę zawartości pliku, po jednej linii na element listy. Następnie możesz po prostu użyć normalnych technik dzielenia listy.
http://docs.python.org/library/stdtypes.html#file.readlines
źródło
@OP, możesz użyć wyliczenia
źródło
Za pomocą instrukcji with otwiera to plik, drukuje linie 26 i 30, a następnie zamyka plik. Prosty!
źródło
readlines()
iteratora wyczerpie się, a drugie wywołanie zwróci pustą listę lub wyrzuci błąd (nie pamiętam, które)Możesz to zrobić bardzo prosto, korzystając ze składni, o której ktoś już wspomniał, ale jest to zdecydowanie najłatwiejszy sposób:
źródło
Aby wydrukować linię nr 3,
Oryginalny autor: Frank Hofmann
źródło
Dość szybko i na temat.
Aby wydrukować określone wiersze w pliku tekstowym. Utwórz listę „lines2print”, a następnie po prostu wydrukuj, gdy wyliczenie jest „na” liście lines2print. Aby pozbyć się dodatkowych „\ n”, użyj line.strip () lub line.strip ('\ n'). Po prostu lubię „rozumienie listy” i staram się używać, kiedy mogę. Lubię metodę „with” do czytania plików tekstowych, aby zapobiec pozostawieniu pliku otwartego z jakiegokolwiek powodu.
lub jeśli lista jest mała, po prostu wpisz listę jako listę do zrozumienia.
źródło
Aby wydrukować żądaną linię. Aby wydrukować linię powyżej / poniżej wymaganej linii.
wykonaj ----> dline („D: \ dummy.txt”, 6) tj. dline („ścieżka pliku”, numer_wiersza, jeśli chcesz, aby górna linia szukanej linii dawała 1 dla dolnej -1, jest to opcjonalna wartość domyślna będzie być zajęty 0)
źródło
Jeśli chcesz odczytać określone linie, takie jak linia rozpoczynająca się po pewnej linii progowej, możesz użyć następujących kodów,
file = open("files.txt","r") lines = file.readlines() ## convert to list of lines datas = lines[11:] ## raed the specific lines
źródło
źródło
Myślę, że to zadziała
źródło