Práce se soubory

Funkce open()

Tato funkce slouží k vytvoření objektu typu file (tento objekt je její návratovou hodnotou), který poskytuje metody pro práci se soubory.

open(nazevSouboru, mod)

Mód je řetězec, který určí jak se bude se souborem zacházet. Může obsahovat následující hodnoty (podobně jako v jazyku C):

Typ Význam
'r' Soubor bude otevřen pro čtení. Pokud neexistuje, nastane výjimka IOError
'r+' Soubor bude otevřen pro čtení a zápis. Pokud neexistuje, nastane výjimka IOError.
'w' Soubor bude otevřen pro zápis. Existující soubor bude zkrácen na nulovou délku, neexistující bude vytvořen.
'a' Soubor bude otevřen pro zápis na konec souboru (append). Neexistující soubor bude vytvořen.
'b' Soubor bude otevřen v binárním režimu. (Znaky nového řádku "\n" nebudou převáděny na platformě závislé "\r", "\r\n" atd.).
't' Soubor bude otevřen v textovém režimu. Toto je defaultní volba, takže se nemusí uvádět. Volby 'b' a 't' pochopitelně není možné použít společně.

S těmito znalostmi již můžete napsat funkci, která bude vracet True v případě existence souboru a False v případě neexistence souboru. Jediný argument této funkce bude název zkoumaného souboru.

>>> def fileexist(nazev):
        try:
                soubor = open(nazev, 'r')
        except IOError:
                return False
        else:
                soubor.close()
                return True

       
>>> fileexist('/tmp/pokus.txt')
False

Pokud vás překvapily lomítka v názvu souboru, pak vězte, že v Linuxu je to normální. Proč jsou v DOSu obráceně ví snad jen Bill Gates. Adresář /tmp/ je také v každém Linuxu. Pokud pracujete s jiným operačním systémem, změňte adresář i lomítka dle libosti.

Python má samozřejmě vlastní funkce na práci se soubory, prostudujte si modul os.path (hned co se naučíte pracovat s moduly).

Metody objektu file

V kapitole o objektech jsem vysvětlil, co jsou to metody. Funkce open() vrací file objekt a pomocí jeho metod se pracuje se souborem.

Metoda close()

Metoda close() má jediný smysl života: uzavírá spojení se souborem. Teprve po použití metody close() máte jistotu, že všechny změny provedené v souboru byly správně uloženy. Také tím uvolníte systémové prostředky počítače, takže na ní nezapomínejte.

Pokud na ní zapomenete, nemusí to být hned tragédie. Po skončení programu to za vás udělá operační systém. Pamatujte ovšem na to, že množství otevřených souborů programem v jeden okamžik je limitováno.

V předchozím příkladě by neměl chybět příkaz soubor.close() po úspěšném otevření souboru (v ostatních případech nebyl soubor otevřen, takže není co zavírat).

Metoda write()

Metoda write() zapíše do souboru data. Pokud je soubor otevřen v textovém režimu (defaultní možnost, když neuvedete mód 'b'), pak se konec řádku "\n" převádí na platformě závislý (tj. ve Windows "\r\n", v Linuxu "\n" …).

Vyzkoušíme na příkladě.
V příkladě otevřeme soubor v aktuálním adresáři jménem pokus.txt. Pokud nebude existovat, vytvoří se. Pak zapíšeme na konec souboru text Hello World a konec řádku. Nakonec soubor uzavřeme, aby se změny zapsali na disk a uvolnili se zdroje pro práci se souborem.

soubor = open('pokus.txt', 'at')
soubor.write('Hello World\n')
soubor.close()

Pokud tyto příkazy zadáte dvakrát, bude v souboru pokus.txt zapsáno Hello World dvakrát, vždy na nové řádce. To proto, že v řetězci 'Hello World\n' je znak konce řádky (speciální znak '\n').

Metoda readlines()

Metoda readlines() vrátí seznam, jehož jednotlivými položkami jsou všechny řádky souboru.

Vytvořte soubor pokus.txt, který bude obsahovat následující:

Prvni radka
Druha radka
Treti radka
Ctvrta radka

Jeho obsah pak zjistíte takto:

>>> try:
        s = open("pokus.txt",'r')
        radky = s.readlines()
except IOError as ex:
        print('Chyba prace se souborem')
else:
        type(radky)
        print(radky)
finally:
        s.close()

<type 'list'>
['Prvni radka\n', 'Druha radka\n', 'Treti radka\n', 'Ctvrta radka\n']

Všiměnte si, že jsou řádky načteny i se speciálním znakem konec řádku '\n'. Toho se můžete zbavit zavoláním metody .rstrip("\n") na každém načteném řádku.

Metoda readline()

Metoda readlines() načte naráz celý soubor. To může být trochu nešikovná při práci s velkými soubory (mít celý soubor v paměti může být náročné). Metoda readline() načte jen jeden řádek a vrátí jej jako řetězec (i s "\n" na konci). Při druhém volání načte druhý řádek, atd. Pokud se dostane na konec souboru, vrací prázdný řetězec (Na konci vrátí "", zatímco prázdný řádek uprostřed souboru bude obsahovat "\n").

Přes objekt file lze iterovat, jako by to byl seznam. V každé iteraci se vrací jedna načtená řádka. Jde o pohodlnější způsob téhož, čehož dosáhnete pomocí metody readline().

>>> s = open('pokus.txt',"r")
>>> for line in s:
     nacteno = 'Načteno: %s' % line
     # print nacteno,              # Python 2.7
     print(nacteno, end="")        # Python 3.0

Načteno: Prvni radka
Načteno: Druha radka
Načteno: Treti radka
Načteno: Ctvrta radka

Metoda read()

Metoda read() načte celý soubor, ale nerozdělí jej do seznamu podle nových řádek jako metoda readline(). Navíc může mít argument typu int (celé číslo), který určí maximální počet načtených bajtů.

Její chování ukáží na souboru pokus.txt z předchozího příkladu.

>>> line = 'X'
>>> s = open('pokus.txt',"r")
>>> while line:
     line = s.read(6)
     nacteno = 'Načteno: %s' % line
     # print nacteno,               # Python 2.7
     print(nacteno, end=" ")        # Python 3.0

Načteno: Prvni  Načteno: radka
 Načteno: Druha  Načteno: radka
 Načteno: Treti  Načteno: radka
 Načteno: Ctvrta Načteno:  radka Načteno:
 Načteno:  >>>

V příkladě jsem využil toho, že prázdný řetězec je chápán jako False. Za předposledním Načteno je schovává znak '\n', za posledním Načteno je již prázdný řetězec (proto je >>> na stejné řádce).

Metody tell() a seek()

Metoda tell() vrací aktuální pozici v souboru v bytech. Její návratovou hodnotou je typ int v rozsahu <0,N-1>, kde N je velikost souboru v bytech.

Metoda seek(pocet, pozice) posune aktuální pozici v souboru o pocet bytů a to od místa pozice. Pokud je pocet záporná hodnota, pak se posune pocet bytů pozice nazpět. Pozice je typu int a může nabývat následujících hodnot:

Hodnota pozice Význam Omezení
0 Začátek souboru
1 Aktuální pozice Funguje jen v binárním režimu.
2 Konec souboru Funguje jen v binárním režimu.

Jen tak mimochodem, nebylo by místo čísel lepší používat výčtový typ?. Výčtový typ je v Pythonu až od verze 3.4, tak kdo ví, třeba se toho v budocnu dočkáme :-)

Metodu seek(pocet) je možno použít s jedním argumentem – potom se implicitně předpokládá posun od začátku souboru.

>>> f = open('workfile', 'wb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5)     # Jdi na šestý bajt v souboru (první je 0)
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # jdi na třetí bajt od konce
13
>>> f.tell()
13
>>> f.read(1)
b'd'
>>> f.tell()
14
Malé b před řetězcem znamená, že se jedná o binární data.

Modul pickle

Modul pickle umožňuje uložit do souboru objekty Pythonu a pak je zase načíst. Můžete tak uložit celé seznamy, nebo vlastní třídy, funkce …

>>> import pickle
>>> def funkce():
    print("Hello World")

>>> seznam = ['ahoj', 3, funkce]
>>> # uložím seznam do souboru do dump.py
>>> pickle.dump(seznam, open("dump.py", "w"))
>>> # a zase si ho načtu
>>> x = pickle.load(open("dump.py", "r"))
>>> x[2]()
Hello World

Podívejte se do souboru dump.py. Všiměte si, jak je tam zapsána funkce – jenom jako odkaz od jmenného prostoru. To má za následek, že pokud Python ukončíte a pokusíte se dump znovu načíst, kvůli neexistenci funkce funkce() se to nepodaří.
Pokud si funkci funkce() definujete, načtení z dump.py se povede, ačkoliv definovaná funkce funkce() může být definovaná úplně jinak než ta, kterou jste se pokusili uložit!

Další detaily se můžete dočíst v dokumentaci.

Moduly os a os.path

V těchto modulech najdete spoustu funkcí na práci se souborovým systémem.

>>> import os
>>> dir(os.path)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_joinrealpath', '_unicode', '_uvarprog', '_varprog', 'abspath',
'altsep', 'basename', 'commonprefix', 'curdir', 'defpath', 'devnull', 'dirname', 'exists', 'expanduser', 'expandvars', 'extsep', 'genericpath',
'getatime', 'getctime', 'getmtime', 'getsize', 'isabs', 'isdir', 'isfile', 'islink', 'ismount', 'join', 'lexists', 'normcase', 'normpath',
'os', 'pardir', 'pathsep', 'realpath', 'relpath', 'samefile', 'sameopenfile', 'samestat', 'sep', 'split', 'splitdrive', 'splitext', 'stat',
'supports_unicode_filenames', 'sys', 'walk', 'warnings']
>>> help(os.path.isdir)
Help on function isdir in module genericpath:

isdir(s)
    Return true if the pathname refers to an existing directory.

>>> os.path.isdir('/tmp/')
True
>>> from os.path import isdir
>>> isdir('/tmp/')
True
>>> os.listdir('/')
['boot', 'home', 'opt', 'srv', 'tmp', 'usr', 'var', 'etc', 'dev', 'proc', 'sys', 'run', 'bin', 'lib', 'lib64', 'root', 'sbin', 'mnt', 'selinux', '.snapshots', 'media', '.readahead']

Modul pathlib

Modul pathlib je novým modulem pro práci s cestami v souborovém systému (od verze Python 3.4). Je zaměřen na zjednodušení práce s různými souborovými systémy (Windows vs Linux). Zatím je v „provizorním„ stádiu vývoje, což znamená, že se mohou v nových verzích vyskytnout nekompatibilní změny (funkce se budou chovat jinak). Takže, pokud budete chtít tento modul používat, tak opatrně.

>>> from pathlib import Path
>>> p = Path('/')
>>> p.is_dir()
True
>>> list(p.glob('*u*'))
[PosixPath('/usr'), PosixPath('/run'), PosixPath('/selinux')]
>>> p = p / 'home' / 'petr'
>>> p
PosixPath('/home/petr')
Komentář Hlášení chyby
Created: 11.9.2005
Last updated: 31.8.2015
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..