Práce se soubory
Na úvod je vhodné zmínit několik slov o konzoli, jenž umožňuje experimentovat či rychle zjišťovat věci ve vývojovém prostředí WinPython. Na výběr máte buď klasický interpret nebo IPython, který má mnohem více možností, ale jen jeho stručný popis by byl na samostatnou kapitolu.
Pokud spustíte nebo ladíte svůj program, tak vám poběží právě zde v konzoli jako nový proces interpretu. V konzoli se pěkně ukazuje krása provázanosti editoru IDE Spyder. Hodnoty vašich proměnných vidíte v okně Variable Explorer.
Pokud napíšete jméno modulu a tečku, hned vám vyskočí seznam dostupných metod a atributů. Jestliže za jménem metody napíšete otevírací závorku, v okně Object inspector se zobrazí její dokumentace (pokud ji lze nalézt). Pokud tedy v hlavním editoru pracujete s objektem, o kterém víte, že je to například řetězec, ale editor to nedokáže rozeznat, je velice příjemné přepnout se zkratkou do konzole, napsat „str.“ a hned máte seznam metod a jejich dokumentaci.
Vytvořme si nyní jednoduchou konzolovou aplikaci, která dokáže sčítat a odčítat dvě čísla. Příklad: >>> print("Kalkulace\n") >>> první_číslo = int(input("Zadejte první číslo: ")) >>> druhé_číslo = int(input("Zadejte druhé číslo: ")) >>> print("Jejich součet je:", první_číslo + druhé_číslo) >>> print("Jejich rozdíl je:", první_číslo - druhé_číslo) >>> input("\nStiskněte libovolnou klávesu...")
Řešení: Kalkulace Zadejte první číslo: 1 Zadejte druhé číslo: 1 Jejich součet je: 2 Jejich rozdíl je: 0 Stiskněte libovolnou klávesu...
Dále se již budeme zabývat problematikou práce se soubory. Téměř všechny programovací jazyky umí operovat s textovými a binárními soubory a Python samozřejmě také. Soubor je reprezentován jako souborový objekt, který obsahuje data o samotném souboru. Před jeho používáním programem ho musíme otevřít, čímž vytvoříme v paměti objekt reprezentující tento soubor. Při otevření specifikujeme i další potřebné informace - jméno souboru, mód přístupu (pouze ke čtení, pouze pro zápis, přidávání, čtení i zápis), velikost vyrovnávací paměti, použité k přístupu k tomuto souboru, aj.
Nový souborový objekt vytvoříme pomocí funkce open(). Příklad: >>> x=open('prac_soubor', 'r') Poznámka – název souboru může obsahovat i cestu k souboru Tato funkce má jeden povinný argument - jméno souboru a jeden nepovinný, který specifikuje mód přístupu (implicitně pouze pro čtení). Funkce může mít také další nepovinný argument, který specifikuje velikost vyrovnávací paměti.
Zůstaňme na chvíli u řetězce, reprezentujícího mód přístupu k souboru. Možnosti módů jsou následující: 'r' - soubor bude otevřen pouze pro čtení, pokud neexistuje 'r+' - soubor bude otevřen pro čtení a zápis, pokud neexistuje 'w' - soubor bude otevřen pouze pro zápis, existující soubor bude zkrácen na nulovou délku, neexistující bude vytvořen 'a' - soubor bude otevřen pro přidávání (zapsaná data budou přidána na konec)
Na systému Windows se lze setkat ještě s modem 'b', který způsobí otevření souboru v binárním módu. Systém rozlišuje mezi textovými a binárními soubory. Z toho vyplývá, že existují i módy jako 'rb', 'wb' a 'r+b'. Opomenutí znaku 'b' může způsobit nemalé problémy! 'b' - soubor bude otevřen v binárním režimu 't' - soubor bude otevřen v textovém režimu (defaultní volba)
Předpokládejme, že existuje souborový objekt. Tento objekt nám poskytuje několik metod (funkcí, které se vážou na tento objekt), pomocí nichž můžeme operovat s obsahem tohoto souboru, viz níže. read() - čtení obsahu souborových objektů readline() - přečte ze souboru jeden řádek a vrátí ho jako řetězec readlines() - přečte všechny řádky ze souboru a vrátí je jako seznam write() - umožňuje zápis do souboru close() - slouží k uzavření souboru
Příklad: >>> x.read() 'Toto je obsah souboru.\n ' >>> x.readline() 'Toto je první řádek souboru.\n' >>> x.readline() 'Toto je druhý řádek souboru.\n‚ >>> x.readlines() ['Toto je první řádek souboru.\n', 'Toto je druhý řádek souboru.\n']
Příklad: >>> x.write(b' abcdef') Poznámka - malé b před řetězcem znamená, že se jedná o binární data. >>> x.close()
Se soubory v Pythonu se tedy pracuje velmi jednoduše – soubor z daného umístění otevřeme, pracujeme s jeho obsahem a na konci ho zase spořádaně uzavřeme: Příklad: >>> x=open('/prac_slozka/prac_soubor', 'r') >>> data=x.readlines() >>> x.close()
Nyní věnujme pozornost následujícímu kódu: >>> with open('/prac_slozka/prac_soubor') as x: data=x.readlines() V tomto kódu se volá open(), ale nikde se v něm nevolá close(). Výhodou daného zápisu je, že když blok with skončí, Python automaticky zavolá close(). Python soubor uzavře nezávisle na tom, jak a kdy blok with skončí i za předpokladu konce, v důsledku neošetřené výjimky.
V souboru je možné se i pohybovat a zjišťovat aktuální pozici (tj. pozici, ze které bude probíhat další čtení a kam se budou zapisovat další data). K těmto účelům slouží metody tell() – zjisti aktuální pozici (offset) ukazatele v souboru, měřenou v bytech od začátku souboru seek() – slouží pro posunutí tohoto ukazatele, první argument specifikuje offset a druhý pozici, ke které se offset vztahuje
Příklad: >>> x=open('/prac_slozka/prac_soubor', 'wb+') >>> x.write(b' abcdef') 16 >>> x.seek(5) # Jdi na šestý bajt v souboru (první je 0) 5 >>> x.read(1) b'5'
Příklad: >>> x.seek(-3, 2) # jdi na třetí bajt od konce 13 >>> x.tell() 13 >>> x.read(1) b'd‚ >>> x.tell() 14
Python dokáže bez problémů zapsat do souboru řetězce. Jestliže však potřebujete číst nebo zapisovat čísla, neobejdete se bez dalšího kódu, který bude provádět případnou konverzi z čísla na řetězec a naopak. Například modul numpy umožňuje velice obratně a efektivně pracovat s vektory, maticemi a n-dimenzionálními poli obecně. Příklad: >>> import numpy as np >>> v = np.array([1,2,3,4]) >>> np.savetxt('matice', v, fmt="%12.6G") >>> np.loadtxt(v) array([ 1., 2., 3., 4.])
Modul rovněž obsahuje sofistikované funkce, nástroje pro integraci C/C ++ a Fortran kódu, funkce pro lineární algebru, Fourierovy transformace a náhodné veličiny. Příklad: >>> import numpy as np >>> M = np.array([[1, 2], [3, 4]]) >>>M.shape (2, 2) >>> np. linalg.inv(M) array([[-2., 1. ], [ 1.5, -0.5]])
V případě, kdy budete chtít zapisovat komplexnější datové typy jako třeba seznamy, slovníky nebo dokonce instance uživatelských tříd, budete muset buď napsat hodně kódu nebo použít již připravený modul pickle. Modul pickle je jedním z vyhrazených prostředků pro perzistentní ukládání dat. To znamená, že například takto uložená data mohou být k dispozici mezi dvěma časově vzdálenými běhy programu (a to i jiného).
Pomocí příslušného pickle-protokolu umí serializovat téměř libovolnou strukturu a uložit ji jako binární objekt (nečitelný v textovém editoru), buď do proměnné nebo do souboru. A samozřejmě ji pak zase umí z proměnné/souboru načíst a převést zpátky do příslušné struktury. Proces serializace se v zásadě uskutečňuje do/z dvou různých míst – paměti nebo proudu (streamu).
do/z paměti: po = pickle.dumps(o) – serializuje objekt o do proměnné po typu bytes() o = pickle.loads(po) – deserializuje bajt-objekt po do datové struktury o do/ze souboru: pickle.dump(o, file) – serializuje objekt o do binárního souboru file o = pickle.load(file) – deserializuje do objektu o serializovanou strukturu v binárním souboru file
Modul pickle dokáže serializovat: všechny Pythonem podporované přirozené datové typy: celá i reálná čísla, komplexní čísla, řetězce, atd. seznamy, n-tice, slovníky a množiny, které obsahují libovolnou kombinaci přirozených datových typů funkce, třídy a instance tříd
Příklad: Předpokládejme, že do souboru zzz chceme uložit nějaký objekt yyy. Jednoduše tak učiníme pomocí funkce pickle.dump() import pickle pickle.dump(yyy, zzz) Pro rekonstrukci objektu ze souboru zzz stačí použít funkci pickle.load() yyy = pickle.load(zzz)
Příklad serializace: >>> import pickle >>> obj1 = (None, 1, 2, 3) >>> obj2 = ['jedna', 'dva', 'atd.'] >>> x = open('/prac_slozka/prac_soubor', 'wb') >>> p = pickle.Pickler(x) >>> p.dump(obj1) >>> p.dump(obj2) >>> x.close()
Příklad deserializace : >>> import pickle >>> x = open('/prac_slozka/prac_soubor', 'rb') >>> u = pickle.Unpickler(x) >>> obj1 = u.load() >>> obj2 = u.load() >>> x.close() >>> print(obj1) (None, 1, 2, 3) >>> print(obj2) ['jedna', 'dva', 'atd.']
Mezi uživateli Pythonu jsou také velmi rozšířené knihovny xml a csv. Modul csv poskytuje jednotné a jednoduché rozhraní pro interakci se soubory, obsahující zejména tabulková data (například soubory typu MS Office Excel aj.). Zápis dat do příslušného souboru lze provést například tímto způsobem: >>> import csv >>> with open('vozidla.csv', 'w', newline='') as voz: a = csv.writer(voz, delimiter=',') data = [['Auto', 'Motorka'], ['293', '219']] a.writerows(data)
Čtení dat z příslušného souboru je patrno z následujícího kódu: >>> import csv >>> ctenidat = csv.reader(open('vozidla.csv'), delimiter=',') >>> for row in ctenidat: print(', '.join(row)) Auto, Motorka 293, 219
Děkuji za Vaši pozornost