# setup
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
Proces czytania i zapisu danych do pliku to zadanie złożone. Python jak większość języków programowania pozwala wczytywać dane ze zbiorów zewnętrznych, jak i zapisywać dane do plików. Proces czytania można zrealizowaćć przy pomocy funkcji wbudowanych open()
, read()
i close()
lub - w przypadku danych o ustalonej strukturze - najczęściej tabelarycznej, można skorzystać z gotowych funkcji wspierających ten proces. W pierwszej kolejności przeanalizujemy proces czytania danych przy pomocy fukcji wbudowanych a następnie pokażemy przykład rozwiązań zewnętrznych.
Aby odczytać plik tekstowy należy wykonać trzy polecenia:
Dodatkowo proces czytania lub zapisu wymaga znalezienia właściwego pliku, lub - w przypadku odczytu utworzenia nowego pliku.
Jako przykład pokażemy wczytanie niewielkiego pliku tekstowego znajdującego się w tym samym katalogu co nasz skrypt.
# -*- coding: utf -8 -*-
f = open("plik.txt")
zawartosc = f.read()
f.close()
zawartosc
Funkcja open()
nawiązuje połączenie z plikiem, ale nie wczytuje danych. Przypisuje jedynie do obiektu f wskaźnik do pliku. Wynika to z faktu że zbiór danych może być bardzo duży i programista powinien zachować kontrolę nad jego wczytywaniem. Funkcja read()
wczytuje całą zawartość ze źródła f (pliku) do zmiennej zawartość. Następnie źródło zostaje zamknięte.
Znak "\n" znajdujący się w obrębie zmiennej oznacza znak końca linii, aby rozbić taką linię na osobne należy zastosować funkcję split(), wskazując znak użyty do rozbicia.
zawartosc.split("\n")
W przypadku dużych plików lepiej zastosować procedurę czytania linia po linii. Czytanie linia po linii jest też operacją stosowaną, gdy chcemy odczytać z pliku konkretne linie:
f = open("plik.txt")
f.readline()
f.readline()
f.readline()
f.close()
W ten sposób możemy kontrolować które linie zostaną zapisane do dalszego przetwarzania.
Funkcja open() domyślnie otwiera plik tekstowy, do odczytu, tym samym wywołanie funkcji open()
jest równoważne open(file,"rt")
. Można również otwierać pliki w innych trybach, na przykład w trybie binarnym ("b") lub w trybie do zapisu ("w"), do zapisu z dołączaniem ("a"), czy w trybie tworzenia nowego pliku ("x").
Ponieważ python wczytuje dane w postaci pojedynczej zmiennej tekstowej, jeżeli wczytane dane zamierzamy poddać obliczeniom, należy je odpowiednio przekształcić, najczęściej do postaci tabelarycznej oraz zmodyfikować typy danych z tekstowych do numerycznych. Do tego celu służą poznane już funkcje split() oraz funkcje konwersji zmiennych. Procedura czytania danych jest następująca:
f = open("tab.csv") #1
dane = f.read() #
dane
dane = dane.split('\n') #2 podziel po liniach
dane = [l.split(',') for l in dane] #2 podziel po wierszach
dane
f.close() #3
header = dane.pop(0) #4 nagłówek
dane.pop() #5 usunięcie ostatniego, pustego wiersza
Dane są przechowywane w postaci listy list, gdzie każda lista zagnieżdżona to pojedynczy wiersz składający się z danych różnego typu. Ponieważ operowanie na wierszach zawierających dane różnego typu nie jest wygodne, można przekształcić listę zagnieżdżoną do postaci kolumnowej (dokonać transpozycji) przy pomocy poznanej wcześniej funkcji zip() Dane przekazujemy z *
czyli rozwijamy przekazaną listę do postaci: dane[0], dane[1],...,dane[n-1]
dane = zip(*dane)
trans = list(dane)
trans
w ostatnim kroku możemy przekształcić 2 i 3 linię do typu integer. Użyjemy do tego mapowania funkcji i funkcji anonimowej:
numery = tuple(map(int,trans[1]))
numery
kody = tuple(map(lambda x: int(x[:3]+x[4:]), trans[2]))
kody
Funkcja anonimowa pobiera pierwszs dwa znaki [:3]
oraz od znaku czwartego do końca [4:]
łączy je w jeden ciąg a następnie zamienia na typ integer. Funkcja map mapuje wynik na całą linię z kodami.
Jeżeli dysponujemy danymi o strukturze tabelarycznej możemy uprościć proces czytania danych oprzez zastosowanie funkcji reader()
z modułu csv.
with
¶W przypadku odczytu danych dobrze jest zamykać proces czytania w obrębie klauzuli with
. Klauzula with pozwala uniknąć problemów w przypadku wystąpienia wyjątku w trkacie wczytywania danych i gwarantuje że po zakończeniu procesu wczytywania połączenie z plikiem zostanie zamknięte. W obrębie kalzuli with powinien się znaleść proces czytania (tworzy generator, nie czyta danych) ora proces zamiany generatora na listę. Jeżeli obie operacje zakończą się sukcesem otrzymamy obiekt z danymi a plik zostanie zamknięty. Jeśli nie obiekt dane nie zostanie utworzony ale połączenie i tak zostanie zamknięte.
import csv
with open('tab.csv') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
dane = list(reader)
dane
Aby zapisać plik tekstowy należy otworzyć go w trybie do zapisu ('w') a następnie zapisać zawartość całego łańcucha funkcją write()
. W przypadku gdy chcemy zapisać listę, należy ją wcześniej zamienić na łańcuch tekstowy, gdyż funkcja write()
może zapisywać tylko łańcucy tekstowe.
mce = ['styczen', 'luty', 'marzec', 'kwiecien', 'maj', 'czerwiec', 'lipiec', 'sierpien', 'wrzesien', 'pazdziernik', 'listopad', 'grudzien']
linia = ",".join(mce)
f = open("wynik.txt",mode='w')
f.write(linia)
f.close()
lub w przypadku listy zapisać wiersz po wierszu, przy pomocy funkcji writelines(). Należy pamiętać konwersji na string i dodaniu znaku końca wiersza. Wykorzystamy do tego funkcję anonimową.
f = open("wynik2.txt",mode='w')
miesiace = map(lambda x: x+'\n',mce)
f.writelines(miesiace)
f.close()
Operacje odczytu i zapisu w języku python są bardzo rozbudowane. Pod tym linkiem można znaleść rozbudowany opis tych i innych operacji wejścia wyjścia. [https://www.tutorialspoint.com/python3/python_files_io.htm]
Tworzone w ramach kodu złożone obiekty na przykład tabele, zagnieżdzonych listy, obiekty klas czy innych struktury istnieją tak długo jak długo wykonywany jest kod, a dokładniej jak długo kod przetwarza blok danych do zasięgu którego należy dany obiekt. Jeżeli obiekt zamierzamy wykorzystać w innych fragmentach kodu, możemy do tego celu użyć obiektu picle, który pozwala na zapis dowolnie złożonej struktury, a następnie wczytanie jej w innym skrypcie. Z pakietu istotne są dwie funkcje dump()
pozwalająca zachować plik oraz load()
przypisująca zawartość pliku do zmiennej. Należy pamiętać, że proces zapisu wymaga wcześniejszego otwarcia pliku, który zamierzamy zepisać lub otworzyć.
Python 2 posiada dwa moduły pickle - starty i bardzo wolny pickle, oraz nowy, napisany w języyku c cpickle. W przypadku użycia Pythona 2 należy linię import pickle
zastępić przez import cpickle as pickle
. Python 3 korzysta już z przyspieszonej wersji modułu.
import pickle
lista = [0,1,2,3,4,[50,51,52,53,54],6]
pickle.dump(lista,open( "plik.p", "wb" ))
pikle = pickle.load(open( "plik.p", "rb" ))
print(pikle)