Blog JSystems - z miłości do programowania

Korzystanie z plików tekstowych, przetwarzanie plików CSV



Czytanie  z plików tekstowych


Najprostsza forma otwarcia pliku do odczytu:


plik = open('dane.txt')


W parametrze funkcji "open" podajemy ścieżkę względną lub bezwzględną do pliku. Jeśli podajemy względną- to w odniesieniu do położenia naszego pliku z kodem.  Jeśli w pliku pojawią się jakiekolwiek znaki spoza alfabetu łacińskiego, to bardzo możliwe że zobaczysz zamiast nich "krzaczki", a wynika to z domyślnego kodowania. Możemy sprawdzić jakie mamy domyślne kodowanie w ten sposób:


import locale
print(locale.getpreferredencoding())


Problem ten możemy rozwiązać stosunkowo łatwo, ponieważ funkcja open przyjmuje także argument dotyczący kodowania jakiego będziemy używać do odczytu pliku:


plik=open('dane.txt', encoding='utf-8')


Do katalogu w którym znajduje się nasz plik z kodem wrzucam plik "dane.txt" o zawartości:


linia 0
linia 1
linia 2
linia 3
linia 4
śćźąęóż


Ostatnią linijkę dodałem w celu sprawdzania poprawności odczytu polskich znaków diakrytycznych. Spróbujmy teraz odczytać plik. Jest na to kilka sposobów w zależności od tego w jakim formacie chcemy mieć zwrócone dane. Sposób odczytu pliku zależy od tego w jaki sposób chcesz go przetwarzać. Generalnie możesz użyć następujących funkcji:



  • read()

  • readlines()

  • readline()


 


read()


Odczytuje plik jako jeden ciągły tekst typu "str":


pl=open('dane.txt', encoding='utf-8')
linie=pl.read()


plik.close()
print(linie)
print(type(linie))


Pojawia nam się tu jeszcze jedna nowa rzecz - zamykanie pliku funkcją "close". Program zadziała nawet jeśli pliku nie zamkniesz po odczycie, ale lepiej to robić by zwalniać zasoby. Wynik na konsoli:


linia 0


linia 1


linia 2


linia 3


linia 4


śćźąęóż


<class 'str'>


Na końcu wyświetliłem też typ odczytanych danych - dla porównania, nie jest to zawartość pliku. Jak widzimy jest to typ "str", czyli po prostu jedna ciągła zmienna tekstowa. Sposób wykorzystania - przydaje się np. gdy chcesz przeszukać cały plik wyrażeniami regularnymi (które są przedmiotem jednego z kolejnych rozdziałów). Pamiętaj że z racji odczytu pliku jako całości, może okazać się że dojdzie do wycieku pamięci z racji jego wielkości. Przyda Ci się więc umiejętność sprawdzenia wielkości pliku. Będziesz mógł wtedy podjąć decyzję o tym czy chcesz wczytywać plik jako całość, czy robić to linia po linii.


Aby sprawdzić wielkość pliku, możesz zastosować poniższą konstrukcję:


import os
ile=os.path.getsize('dane.txt')
print(ile)


Do zmiennej "ile" zostanie przypisana wielkość pliku w bajtach.  Jest jeszcze jedna alternatywa. Możesz użyć parametru funkcji "read" określającego ile znaków ma zostać wczytane:


plik=open('dane.txt',encoding='utf-8')
linie=plik.read(20)
print(linie)
print("-------------------")
linie=plik.read(20)
print(linie)


Wynik na konsoli:


linia 0


linia 1


lini


-------------------


a 2


linia 3


linia 4


 


readlines()


Podobnie jak funkcja "read" odczytuje całą zawartość pliku na raz. Różnica tkwi w zwracanym typie, ponieważ tym razem dostaniemy listę - każda linijka w pliku znajdzie się w kolejnym elemencie listy.


pl=open('dane.txt', encoding='utf-8')
linie=pl.readlines()


pl.close()
print(linie)
print(type(linie))


Wynik z konsoli:


['linia 0\n', 'linia 1\n', 'linia 2\n', 'linia 3\n', 'linia 4\n', 'śćźąęóż']


<class 'list'>


Znacznik "\n" to znacznik końca linii. Możesz się go pozbyć używając funkcji "split" na każdym z elementów listy, lub zastosować nieco zmodyfikowany sposób korzystania z funkcji "read":


pl=open('dane.txt', encoding='utf-8')
linie=pl.read().splitlines()


pl.close()
print(linie)
print(type(linie))


Skutek podobny, ponieważ w obu przypadkach czytamy cały plik a w wyniku dostajemy listę pozbawioną znaczników końca linii:


['linia 0', 'linia 1', 'linia 2', 'linia 3', 'linia 4', 'śćźąęóż']


<class 'list'>


 


readline()


Służy do odczytu pliku linia po linii. Przydatne na przykład gdy chcesz przeszukiwać plik aż do znalezienia jakiegoś fragmentu tekstu. Nie zawsze jest potrzebne czytanie całego (często bardzo dużego pliku). Poniżej przykład konstrukcji pozwalającej czytać plik linia po linii:       


with open('dane.txt',encoding='utf-8') as f:
    for l in f:
        print(l)


f.close()


 


Funkcja seek()


Funkcja "seek" przesuwa kursor do wskazanej pozycji - numer znaku w pliku. Jeśli nie podasz parametru, funkcja domyślnie przyjmie wartość "0".  Przypuśćmy że otworzyliśmy plik i odczytaliśmy z niego dane, po czym ponownie zechcemy odczytać jego zawartość. Poniższy kod


plik=open('dane.txt',encoding='utf-8')
linie=plik.readlines()
print(linie)
linie=plik.readlines()
print(linie)


plik.close()


drukuje na konsoli taki wynik:


['linia 0\n', 'linia 1\n', 'linia 2\n', 'linia 3\n', 'linia 4\n', 'śćźąęóż']


[]


Jak widzisz ponowny odczyt funkcją "readlines" zwraca nam pustą listę. Wynika to z faktu, że po pierwszym odczycie kursor został przesunięty na koniec pliku, więc kolejne wywołanie "readlines()" nie ma już co czytać.


Wykorzystując funkcję "seek" możemy ponownie przesunąć kursor na początek pliku:


plik=open('dane.txt',encoding='utf-8')
linie=plik.readlines()
print(linie)
plik.seek(0)
linie=plik.readlines()
print(linie)


plik.close()


Tym razem na konsoli dostajemy taki wynik:


['linia 0\n', 'linia 1\n', 'linia 2\n', 'linia 3\n', 'linia 4\n', 'śćźąęóż']


['linia 0\n', 'linia 1\n', 'linia 2\n', 'linia 3\n', 'linia 4\n', 'śćźąęóż']


 


Sprawdzanie ilości linii w pliku


Aby sprawdzić ilość wierszy w pliku musimy go niestety w całości przeczytać. Nie jest to najwydajniejsze, ale niestety nie ma alternatywy. Możemy to zrobić np. w ten sposób:


plik=open('dane.txt',encoding='utf-8')
linie=plik.readlines()
print('liczba wierszy w pliku={}'.format(len(linie)))


plik.close()


Powyższy sposób sprowadza się do odczytania wszystkich linii z pliku jako listy i sprawdzenia ilości elementów na liście.


 


Zapis w plikach tekstowych


Tryby otwarcia pliku


Aby zapisywać do pliku musimy w funkcji open podać wartość dodatkowego parametru "mode". W zależności od tego czy chcemy nadpisać ewentualnie istniejącą zawartość, czy dopisywać, czy może jednocześnie móc czytać i pisać do tego samego pliku, używamy jednej z poniższych instrukcji. Jeśli chcemy nadpisać ewentualną zawartość stosujemy przełącznik "w":


plik=open('nowy.txt',encoding='utf-8',mode='w')


aby dopisywać używamy "a":


plik=open('nowy.txt',encoding='utf-8',mode='a')


Oba powyższe tryby powodują stworzenie pliku jeśli taki by nie istniał. Jeśli chcemy jednocześnie pisać i czytać używamy "r+":


plik=open('nowy.txt',encoding='utf-8',mode='r+')


 


Wprowadzanie danych do pliku


Najprostszy sposób pisania do plików:


plik=open('nowy.txt',encoding='utf-8',mode='w')
for x in range(10):
    plik.write(str(x))
plik.close()


Tym sposobem do pliku zapiszemy ciąg "0123456789". Każda kolejna wartość znajdzie się w tej samej linii.


 Jeśli chcesz zapisać kolejne wartości w kolejnych liniach, wystarczy dodać znacznik "\n":


plik=open('nowy.txt',encoding='utf-8',mode='w')
for x in range(10):
    plik.write(str(x)+"\n")
plik.close()


Python umożliwia też zapis do pliku od razu całej listy elementów.  Obrazuje to poniższy przykład:


plik=open('nowy.txt',encoding='utf-8',mode='w')
linie=[]
for x in range(10):
    linie.append("linia numer {} \n".format(x))
plik.writelines(linie) # to nas interesuje
plik.close()


Najpierw przygotuję sobie listę wartości które mają zostać zapisane (umieszczając w każdej znacznik "\n" by wartości te znajdowały się w kolejnych liniach. Nie musi to być konkretnie lista, może to być dowolny iterowalny element zawierający ciągi tekstowe.

Przyjdź do nas na szkolenie z języka Python! Mamy szereg szkoleń w ofercie, od podstawowych po aplikacje webowe z użyciem Django, analizę danych, tesowanie, machine learning i wiele innych.
Sprawdź dostępne szkolenia Python
Zapisz się do newslettera aby otrzymywać najnowsze świeżynki pojawiające się na blogu!