Základní práci se soubory – čtení z nich a psaní do nich – rozebírá lekce o souborech. Pro zopakování:
# Otevření textového souboru "basnicka.txt" pro čtení
with open('basnicka.txt', encoding='utf-8') as soubor:
# Přečtení obsahu
contents = soubor.read()
# Velikost souboru
print(len(soubor))
Jméno souboru, případně cesta k němu, se tradičně zadává jako řetězec. Jednotlivé adresáře jsou odděleny lomítkem (případně na Windows zpětným lomítkem); fungují tu absolutní i relativní cesty.
Pro prosté otvírání známých souborů to stačí. Když ale potřebuješ s cestami k souborům pracovat víc, řetězce jsou docela nepohodlné. A navíc je problém pamatovat na všechny různé případy, které můžou nastat.
Zkus pro příkad napsat funkce, které dostanou cestu k souboru a:
vrat_casti
rozdělí cestu na jednotlivé adresáře (a vrátí je jako seznam),vrat_priponu
vrátí příponu souboru.Na mém Linuxovém počítači cesty vypadají jako
/home/janca/Documents/archiv.tar.gz
, takže bych mohl napsat něco jako:
def vrat_casti(path):
"""Vrátí seznam komponentů cesty (jednotlivých adresářů/souborů)"""
return path.split('/')
def vrat_priponu(path):
"""Vrátí příponu souboru"""
parts = path.split('.')
return parts[-1]
Pro mou cestu to funguje:
>>> retezcova_cesta = '/home/janca/Documents/archiv.tar.gz'
>>> vrat_casti(retezcova_cesta)
['', 'home', 'janca', 'Documents', 'archiv.tar.gz']
>>> vrat_pripona(retezcova_cesta)
'gz'
Ale pro jinou cestu na jiném počítači už ne:
>>> retezcova_cesta = 'C:\\Users\\Jana\\Programy\\superprojekt\\README'
>>> vrat_casti(retezcova_cesta)
['C:\\Users\\Jana\\Programy\\superprojekt\\README']
>>> vrat_priponu(retezcova_cesta)
'C:\Users\Jana\Programy\superprojekt\README'
To, že programátoři používali na cesty řetězce a nepromýšleli všechny možné podivnosti souborových systémů, je hlavní důvod proč si ještě dnes spousta programů neporadí s diakritikou nebo mezerami v názvech souborů.
Jde to líp? Samozřejmě!
Od verze 3.4 obsahuje Python knihovnu pathlib
, jejíž třída Path
reprezentuje
cestu k souboru a umožňuje s takovými cestami jednoduše a bezpečně manipulovat.
>>> from pathlib import Path
>>> # Cesta, která na Windows i Unixu funguje podobně:
>>> cesta = Path('/home/janca/Documents/archiv.tar.gz')
>>> cesta.parts
('/', 'home', 'janca', 'Documents', 'archiv.tar.gz')
>>> cesta.suffix
'.gz'
Ukázka s cestou pro Windows (která by na Unixu nefungovala):
Pouštíš-li ukázku na Windows, můžeš místo PureWindowsPath
použít rovnou
Path
.
>>> from pathlib import PureWindowsPath
>>> win_cesta = PureWindowsPath('C:\\Users\\Jana\\Programy\\superprojekt\\README')
>>> win_cesta.parts
('C:\\', 'Users', 'Jana', 'Programy', 'superprojekt', 'README')
>>> win_cesta.suffix
''
Ukažme si teď něco z toho, co pathlib
umožňuje.
Nebude to všechno – další možnosti najdeš na taháku nebo v angličtině
v dokumentaci.
Cesty v pathlib
se tvoří zavoláním třídy Path
.
Na Windows se tím vytvoří WindowsPath
, na Unixu PosixPath
.
Obě považují dopředná lomítka za oddělovač adresářů, takže následující bude fungovat na všech systémech:
>>> docs_cesta = Path('/home/janca/Documents')
>>> docs_cesta
PosixPath('/home/janca/Documents')
Už při vytvoření cesty se tato normalizuje, zjednoduší bez změny významu. Víc lomítek za sebou se spojí do jednoho, zbytečné adresáře nebo lomítka na konci se vynechají.
>>> Path('/tmp//foo/./bar/')
PosixPath('/tmp/foo/bar')
Když chci k takové cestě něco připojit, použiju operátor /
(který by se měl
používat na dělení, ale psst!):
>>> docs_cesta / 'archiv.tar.gz'
PosixPath('/home/janca/Documents/archiv.tar.gz')
Přidávat se takhle dají řetězcové cesty, nebo i další Path
:
>>> Path('/') / 'home/janca' / Path('archiv.tar.gz')
PosixPath('/home/janca/archiv.tar.gz')
Pozor ale na to, že absolutní cesta (s lomítkem nebo jménem disku na začátku) znamená, že procházení začíná znovu od kořenového adresáře. Když k něčemu připojím absolutní cestu, předchozí cesta se zahodí.
>>> Path('/home/janca') / '/tmp/foo'
PosixPath('/tmp/foo')
Občas lomítko není pohodlné.
V takových případech jde použít metoda joinpath
, která má stejný efekt:
>>> Path('/').joinpath('home', 'janca/archiv.tar.gz')
PosixPath('/home/janca/archiv.tar.gz')
Cesty v pathlib mají spoustu užitečných atributů – vlastností, ke kterým se dostaneš pomocí tečky:
>>> # Příklady ukážeme opět na téhle cestě:
>>> cesta = Path('/home/janca/Documents/archiv.tar.gz')
>>> cesta
PosixPath('/home/janca/Documents/archiv.tar.gz')
>>> # jméno
>>> cesta.name
'archiv.tar.gz'
>>> # Přípona (poslední)
>>> cesta.suffix
'.gz'
>>> # Věchny přípony
>>> cesta.suffixes
['.tar', '.gz']
>>> # "kořen" jména (bez poslední přípony)
>>> cesta.stem
'archiv.tar'
>>> # "rodič" – adresář, který tuto cestu obsahuje
>>> cesta.parent
PosixPath('/home/janca/Documents')
>>> cesta.parent.parent
PosixPath('/home/janca')
>>> cesta.parent.parent.parent.parent
PosixPath('/')
Všechny "předky" -- rodiče, prarodiče, atd. -- nabízí atribut "parents".
Výsledek je ale iterátor; aby se ukázaly jednotlivé hodnoty,
je potřeba ho projít cyklem for
, převést na seznam, atp.
>>> cesta.parents
<PosixPath.parents>
>>> list(cesta.parents)
[PosixPath('/home/janca/Documents'),
PosixPath('/home/janca'),
PosixPath('/home'),
PosixPath('/')]
>>> # Je cesta absolutní?
>>> cesta.is_absolute()
True
>>> Path('foo/archiv.zip').is_absolute()
False
>>> # Jaká by byla relativní vzhledem k jiné, nadřazené cestě?
>>> relativni_cesta = cesta.relative_to('/home/janca')
>>> relativni_cesta
PosixPath('Documents/archiv.tar.gz')
>>> # Spojením té nadřazené cesty a této relativní dostanu zpátky původní cestu
>>> Path('/home/janca') / relativni_cesta
PosixPath('/home/janca/Documents/archiv.tar.gz')
>>> # Přepsání jména souboru (poslední části cesty)
>>> cesta.with_name('hrad.jpeg')
PosixPath('/home/janca/Documents/hrad.jpeg')
>>> # Přepsání koncovky
>>> cesta.with_suffix('.bz2')
PosixPath('/home/janca/Documents/archiv.tar.bz2')
>>> # Pokud existující koncovka není, `with_suffix` ji přidá
>>> Path('myproject/README').with_suffix('.xz')
PosixPath('myproject/README.xz')
Všechno uvedené výše jsou čistě „textové“ operace – pracují jen se jmény.
Soubor archiv.zip
(ani jiné) počítači mít, aby ses dostala k příponě
nebo ke jménům nadřazených adresářů.
Dokonce si můžeš vyzkoušet, jak by to fungovalo na jiném systému – místo Path
naimportuj a použij PureWindowsPath
nebo PurePosixPath
, které reprezentují
Windowsové, resp. Unixové cesty.
Zamysli se: k čemu se hodí umět pojmenovat soubor, který neexistuje?
Teď se dostaneme k operacím pro které je potřeba mít přístup k souborovému systému.
Nejdříve dvě funkce, které vrací cesty k užitečným adresářům:
>>> # Aktuální adresář
>>> Path.cwd()
PosixPath('/home/janca/pyladies/barvy')
>>> # Můj domovský adresář
>>> Path.home()
PosixPath('/home/janca')
A základní otázky – existuje daný soubor? Je to normální soubor nebo adresář?
>>> # Existuje na té ukázkové cestě nějaký soubor?
>>> cesta.exists()
False
>>> # Existuje můj domovský adresář?
>>> Path.home().exists()
True
>>> # A je to vůbec adresář?
>>> Path.home().is_dir()
True
>>> # Je to normální datový soubor?
>>> Path.home().is_file()
False
Abychom měli všichni stejné podmínky, stáhni si na další experimenty
archiv s testovacími soubory.
Dej si ho do aktuálního adresáře (Path.cwd()
), a pak ho rozbal pomocí
tarfile
:
>>> import tarfile
>>> cesta_k_archivu = Path("archiv.tar.gz")
>>> # Co je v archivu?
>>> tarfile.open(cesta_k_archivu, 'r|gz').getnames()
['soubory',
'soubory/hrad.jpeg',
'soubory/hrad.attribution',
'soubory/.gitignore',
'soubory/kolecko.png',
'soubory/texty',
'soubory/texty/vodnik.txt',
'soubory/texty/lidove',
'soubory/texty/lidove/pes.txt',
'soubory/texty/lidove/holka.txt',
'soubory/texty/vladimir.txt',
'soubory/texty/cizojazycne',
'soubory/texty/cizojazycne/iroha.txt',
'soubory/texty/cizojazycne/witch.txt',
'soubory/hlad.txt',
'soubory/hraz.attribution',
'soubory/ententyky.txt',
'soubory/hraz.jpeg',
'soubory/README']
>>> # Extrakce archivu. (Kdybys to zkoušel/a pro jiné archivy, vždy před
>>> # rozbalením zkontroluj cesty všech souborů v archivu -- ať se rozbalením
>>> # nepřepíše nějaký důležitý soubor!)
>>> tarfile.open(cesta_k_archivu, 'r|gz').extractall()
Rozbalením archivu vznikl ./soubory/
(tedy: adresář soubory
v aktuálním
adresáři).
Pojď se mu kouknout na zoubek:
>>> zaklad = Path('./soubory')
>>> zaklad
PosixPath('soubory')
>>> print('Je to adresář?', zaklad.is_dir())
Je to adresář? True
>>> print('Je to normální soubor?', zaklad.is_file())
Je to normální soubor? False
Podle informací o archivu je v soubory nějaký ententyky.txt
– podle přípony
soubor s textem.
>>> ententyky = zaklad / 'ententyky.txt'
>>> print('Je to adresář?', ententyky.is_dir())
Je to adresář? False
>>> print('Je to normální soubor?', ententyky.is_file())
Je to normální soubor? True
Objekty Path
lze používat v naprosté většině situací, kdy jde použít cesta
jako řetězec.
Například pro funkci open
:
with open(ententyky, encoding='utf-8') as file:
print(file.read())
Path
ale má open
i jako metodu:
with ententyky.open(encoding='utf-8') as file:
print(file.read())
A protože je čtení celého textového obsahu souboru docela užitečné, existuje i zkratka která soubor otevře, přečte a zavře najednou:
print(ententyky.read_text())
(Větší soubory je ale lepší otevřít ve with
a zpracovávat třeba po řádcích,
aby se obsah nemusel do paměti počítače načíst celý najednou.)
Existuje i write_text
:
cesta = Path.cwd() / 'pisnicka.txt'
cesta.write_text('Holka modrooká\nNesedávej u potoka!')
I s adresáři umí pathlib
pracovat.
Nejzákladnější operace je získání cest k obsaženým souborům:
>>> zaklad.iterdir()
<generator object Path.iterdir at 0x7fbd4443b9e8>
Metoda iterdir opět vrací iterátor – objekt, přes který musíš „projít“ (cyklem for, převedením na seznam ap.), abys z něj dostala obsah.
>>> list(zaklad.iterdir())
[PosixPath('soubory/hrad.jpeg'),
PosixPath('soubory/hrad.attribution'),
PosixPath('soubory/.gitignore'),
PosixPath('soubory/kolecko.png'),
PosixPath('soubory/texty'),
PosixPath('soubory/hlad.txt'),
PosixPath('soubory/hraz.attribution'),
PosixPath('soubory/ententyky.txt'),
PosixPath('soubory/hraz.jpeg'),
PosixPath('soubory/README')]
>>> for cesta in zaklad.iterdir():
>>> print(cesta)
soubory/hrad.jpeg
soubory/hrad.attribution
soubory/.gitignore
soubory/kolecko.png
soubory/texty
soubory/hlad.txt
soubory/hraz.attribution
soubory/ententyky.txt
soubory/hraz.jpeg
soubory/README
Adresáře, podadresáře a soubory v nich tvoří strukturu, na kterou se často používají rekurzivní funkce.
Tady je funkce vypis_soubory
, která ypíše všechny soubory v daném adresáři.
Před každé jméno dá odrážku -
, aby to líp vypadalo:
from pathlib import Path
def vypis_soubory(odrazka, adresar):
"""Vypíše odrážkový seznam jmen souborů v daném adresáři"""
for soubor in adresar.iterdir():
print(odrazka, soubor.name)
vypis_soubory('-', Path.cwd())
Odrážka se dá zadat:
vypis_soubory('*', Path.cwd())
vypis_soubory(' *', Path.cwd())
Tahle funkce se dá změnit, aby vypsala i obsahy podadresářů. Jak? Poté, co vypíše jméno nějakého podadresáře, zavolá funkci která vypíše obsah toho podadresáře. Takovou funkci ale už máš napsanou – stačí trochu změnit odrážku, aby bylo poznat co je podadresář.
from pathlib import Path
def vypis_soubory(odrazka, adresar):
"""Vypíše odrážkový seznam jmen souborů v daném adresáři i podadresářích"""
for soubor in adresar.iterdir():
print(odrazka, soubor.name)
if soubor.is_dir():
vypis_soubory(' ' + odrazka, soubor)
vypis_soubory('-', Path.cwd())
Podobně lze například spočítat soubory v nějakém adresáři (i všech podadresářích).
from pathlib import Path
def spocitej_normalni_soubory(adresar):
"""Vrátí počet normálních souborů v daném adresáři i všech podadresářích"""
pocet = 0
for soubor in adresar.iterdir():
if soubor.is_dir():
pocet = pocet + spocitej_normalni_soubory(soubor)
elif soubor.is_file():
pocet = pocet + 1
return pocet
print(spocitej_normalni_soubory(Path.cwd()))
{ "data": { "sessionMaterial": { "id": "session-material:2019/brno-podzim-pondeli:iterable:3", "title": "Adresáře, soubory a cesty", "html": "\n \n \n\n <h1>Cesty a soubory s Pathlib</h1>\n<p>Základní práci se soubory – čtení z nich a psaní do nich – rozebírá\n<a href=\"/2019/brno-podzim-pondeli/beginners/files/\">lekce o souborech</a>. Pro zopakování:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"c1\"># Otevření textového souboru "basnicka.txt" pro čtení</span>\n<span class=\"k\">with</span> <span class=\"nb\">open</span><span class=\"p\">(</span><span class=\"s1\">'basnicka.txt'</span><span class=\"p\">,</span> <span class=\"n\">encoding</span><span class=\"o\">=</span><span class=\"s1\">'utf-8'</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"n\">soubor</span><span class=\"p\">:</span>\n <span class=\"c1\"># Přečtení obsahu</span>\n <span class=\"n\">contents</span> <span class=\"o\">=</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">read</span><span class=\"p\">()</span>\n\n<span class=\"c1\"># Velikost souboru</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">soubor</span><span class=\"p\">))</span>\n</pre></div><p>Jméno souboru, případně cesta k němu, se tradičně zadává jako řetězec.\nJednotlivé adresáře jsou odděleny lomítkem (případně na Windows zpětným lomítkem);\nfungují tu absolutní i relativní cesty.</p>\n<p>Pro prosté otvírání známých souborů to stačí.\nKdyž ale potřebuješ s cestami k souborům pracovat víc,\nřetězce jsou docela nepohodlné.\nA navíc je problém pamatovat na všechny různé případy, které můžou nastat.</p>\n<p>Zkus pro příkad napsat funkce, které dostanou cestu k souboru a:</p>\n<ul>\n<li><code>vrat_casti</code> rozdělí cestu na jednotlivé adresáře (a vrátí je jako seznam),</li>\n<li><code>vrat_priponu</code> vrátí příponu souboru.</li>\n</ul>\n<p>Na mém Linuxovém počítači cesty vypadají jako\n<code>/home/janca/Documents/archiv.tar.gz</code>, takže bych mohl napsat něco jako:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">vrat_casti</span><span class=\"p\">(</span><span class=\"n\">path</span><span class=\"p\">):</span>\n <span class=\"sd\">"""Vrátí seznam komponentů cesty (jednotlivých adresářů/souborů)"""</span>\n <span class=\"k\">return</span> <span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s1\">'/'</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">vrat_priponu</span><span class=\"p\">(</span><span class=\"n\">path</span><span class=\"p\">):</span>\n <span class=\"sd\">"""Vrátí příponu souboru"""</span>\n <span class=\"n\">parts</span> <span class=\"o\">=</span> <span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s1\">'.'</span><span class=\"p\">)</span>\n <span class=\"k\">return</span> <span class=\"n\">parts</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span>\n</pre></div><p>Pro mou cestu to funguje:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">retezcova_cesta</span> <span class=\"o\">=</span> <span class=\"s1\">'/home/janca/Documents/archiv.tar.gz'</span>\n\n<span class=\"gp\">>>> </span><span class=\"n\">vrat_casti</span><span class=\"p\">(</span><span class=\"n\">retezcova_cesta</span><span class=\"p\">)</span>\n<span class=\"go\">['', 'home', 'janca', 'Documents', 'archiv.tar.gz']</span>\n<span class=\"gp\">>>> </span><span class=\"n\">vrat_pripona</span><span class=\"p\">(</span><span class=\"n\">retezcova_cesta</span><span class=\"p\">)</span>\n<span class=\"go\">'gz'</span>\n</pre></div><p>Ale pro jinou cestu na jiném počítači už ne:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">retezcova_cesta</span> <span class=\"o\">=</span> <span class=\"s1\">'C:</span><span class=\"se\">\\\\</span><span class=\"s1\">Users</span><span class=\"se\">\\\\</span><span class=\"s1\">Jana</span><span class=\"se\">\\\\</span><span class=\"s1\">Programy</span><span class=\"se\">\\\\</span><span class=\"s1\">superprojekt</span><span class=\"se\">\\\\</span><span class=\"s1\">README'</span>\n\n<span class=\"gp\">>>> </span><span class=\"n\">vrat_casti</span><span class=\"p\">(</span><span class=\"n\">retezcova_cesta</span><span class=\"p\">)</span>\n<span class=\"go\">['C:\\\\Users\\\\Jana\\\\Programy\\\\superprojekt\\\\README']</span>\n<span class=\"gp\">>>> </span><span class=\"n\">vrat_priponu</span><span class=\"p\">(</span><span class=\"n\">retezcova_cesta</span><span class=\"p\">)</span>\n<span class=\"go\">'C:\\Users\\Jana\\Programy\\superprojekt\\README'</span>\n</pre></div><div class=\"admonition note\"><p>To, že programátoři používali na cesty řetězce a nepromýšleli všechny možné\npodivnosti souborových systémů, je hlavní důvod proč si ještě dnes spousta\nprogramů neporadí s diakritikou nebo mezerami v názvech souborů.</p>\n</div><p>Jde to líp? Samozřejmě!</p>\n<h2>Knihovna pathlib</h2>\n<p>Od verze 3.4 obsahuje Python knihovnu <code>pathlib</code>, jejíž třída <code>Path</code> reprezentuje\ncestu k souboru a umožňuje s takovými cestami jednoduše a bezpečně manipulovat.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Cesta, která na Windows i Unixu funguje podobně:</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca/Documents/archiv.tar.gz'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parts</span>\n<span class=\"go\">('/', 'home', 'janca', 'Documents', 'archiv.tar.gz')</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">suffix</span>\n<span class=\"go\">'.gz'</span>\n</pre></div><p>Ukázka s cestou pro Windows (která by na Unixu nefungovala):</p>\n<div class=\"admonition note\"><p>Pouštíš-li ukázku na Windows, můžeš místo <code>PureWindowsPath</code> použít rovnou\n<code>Path</code>.</p>\n</div><div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">PureWindowsPath</span>\n\n<span class=\"gp\">>>> </span><span class=\"n\">win_cesta</span> <span class=\"o\">=</span> <span class=\"n\">PureWindowsPath</span><span class=\"p\">(</span><span class=\"s1\">'C:</span><span class=\"se\">\\\\</span><span class=\"s1\">Users</span><span class=\"se\">\\\\</span><span class=\"s1\">Jana</span><span class=\"se\">\\\\</span><span class=\"s1\">Programy</span><span class=\"se\">\\\\</span><span class=\"s1\">superprojekt</span><span class=\"se\">\\\\</span><span class=\"s1\">README'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">win_cesta</span><span class=\"o\">.</span><span class=\"n\">parts</span>\n<span class=\"go\">('C:\\\\', 'Users', 'Jana', 'Programy', 'superprojekt', 'README')</span>\n<span class=\"gp\">>>> </span><span class=\"n\">win_cesta</span><span class=\"o\">.</span><span class=\"n\">suffix</span>\n<span class=\"go\">''</span>\n</pre></div><p>Ukažme si teď něco z toho, co <code>pathlib</code> umožňuje.\nNebude to všechno – další možnosti najdeš <a href=\"https://pyvec.github.io/cheatsheets/pathlib/pathlib-cs.pdf\">na taháku</a> nebo v angličtině\nv <a href=\"https://docs.python.org/3/library/pathlib.html\">dokumentaci</a>.</p>\n<h2>Tvoření cest</h2>\n<p>Cesty v <code>pathlib</code> se tvoří zavoláním třídy <code>Path</code>.\nNa Windows se tím vytvoří <code>WindowsPath</code>, na Unixu <code>PosixPath</code>.</p>\n<p>Obě považují dopředná lomítka za oddělovač adresářů,\ntakže následující bude fungovat na všech systémech:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">docs_cesta</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca/Documents'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">docs_cesta</span>\n<span class=\"go\">PosixPath('/home/janca/Documents')</span>\n</pre></div><p>Už při vytvoření cesty se tato <em>normalizuje</em>, zjednoduší bez změny významu.\nVíc lomítek za sebou se spojí do jednoho, zbytečné adresáře nebo lomítka na\nkonci se vynechají.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/tmp//foo/./bar/'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('/tmp/foo/bar')</span>\n</pre></div><p>Když chci k takové cestě něco připojit, použiju operátor <code>/</code> (který by se měl\npoužívat na dělení, ale psst!):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">docs_cesta</span> <span class=\"o\">/</span> <span class=\"s1\">'archiv.tar.gz'</span>\n<span class=\"go\">PosixPath('/home/janca/Documents/archiv.tar.gz')</span>\n</pre></div><p>Přidávat se takhle dají řetězcové cesty, nebo i další <code>Path</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/'</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"s1\">'home/janca'</span> <span class=\"o\">/</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'archiv.tar.gz'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('/home/janca/archiv.tar.gz')</span>\n</pre></div><p>Pozor ale na to, že absolutní cesta (s lomítkem nebo jménem disku na začátku)\nznamená, že procházení začíná znovu od kořenového adresáře.\nKdyž k něčemu připojím absolutní cestu, předchozí cesta se zahodí.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca'</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"s1\">'/tmp/foo'</span>\n<span class=\"go\">PosixPath('/tmp/foo')</span>\n</pre></div><p>Občas lomítko není pohodlné.\nV takových případech jde použít metoda <code>joinpath</code>, která má stejný efekt:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">joinpath</span><span class=\"p\">(</span><span class=\"s1\">'home'</span><span class=\"p\">,</span> <span class=\"s1\">'janca/archiv.tar.gz'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('/home/janca/archiv.tar.gz')</span>\n</pre></div><h2>Atributy</h2>\n<p>Cesty v pathlib mají spoustu užitečných atributů – vlastností, ke kterým se\ndostaneš pomocí tečky:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"c1\"># Příklady ukážeme opět na téhle cestě:</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca/Documents/archiv.tar.gz'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span>\n<span class=\"go\">PosixPath('/home/janca/Documents/archiv.tar.gz')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># jméno</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">name</span>\n<span class=\"go\">'archiv.tar.gz'</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Přípona (poslední)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">suffix</span>\n<span class=\"go\">'.gz'</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Věchny přípony</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">suffixes</span>\n<span class=\"go\">['.tar', '.gz']</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># "kořen" jména (bez poslední přípony)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">stem</span>\n<span class=\"go\">'archiv.tar'</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># "rodič" – adresář, který tuto cestu obsahuje</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parent</span>\n<span class=\"go\">PosixPath('/home/janca/Documents')</span>\n\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">parent</span>\n<span class=\"go\">PosixPath('/home/janca')</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">parent</span>\n<span class=\"go\">PosixPath('/')</span>\n</pre></div><p>Všechny "předky" -- rodiče, prarodiče, atd. -- nabízí atribut "parents".\nVýsledek je ale <em>iterátor</em>; aby se ukázaly jednotlivé hodnoty,\nje potřeba ho projít cyklem <code>for</code>, převést na seznam, atp.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parents</span>\n<span class=\"go\"><PosixPath.parents></span>\n\n<span class=\"gp\">>>> </span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">parents</span><span class=\"p\">)</span>\n<span class=\"go\">[PosixPath('/home/janca/Documents'),</span>\n<span class=\"go\"> PosixPath('/home/janca'),</span>\n<span class=\"go\"> PosixPath('/home'),</span>\n<span class=\"go\"> PosixPath('/')]</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Je cesta absolutní?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">is_absolute</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'foo/archiv.zip'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">is_absolute</span><span class=\"p\">()</span>\n<span class=\"go\">False</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Jaká by byla relativní vzhledem k jiné, nadřazené cestě?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">relativni_cesta</span> <span class=\"o\">=</span> <span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">relative_to</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">relativni_cesta</span>\n<span class=\"go\">PosixPath('Documents/archiv.tar.gz')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Spojením té nadřazené cesty a této relativní dostanu zpátky původní cestu</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'/home/janca'</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"n\">relativni_cesta</span>\n<span class=\"go\">PosixPath('/home/janca/Documents/archiv.tar.gz')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Přepsání jména souboru (poslední části cesty)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">with_name</span><span class=\"p\">(</span><span class=\"s1\">'hrad.jpeg'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('/home/janca/Documents/hrad.jpeg')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Přepsání koncovky</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">with_suffix</span><span class=\"p\">(</span><span class=\"s1\">'.bz2'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('/home/janca/Documents/archiv.tar.bz2')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Pokud existující koncovka není, `with_suffix` ji přidá</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'myproject/README'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">with_suffix</span><span class=\"p\">(</span><span class=\"s1\">'.xz'</span><span class=\"p\">)</span>\n<span class=\"go\">PosixPath('myproject/README.xz')</span>\n</pre></div><h2>Zkoumání disku</h2>\n<p>Všechno uvedené výše jsou čistě „textové“ operace – pracují jen se jmény.\nSoubor <code>archiv.zip</code> (ani jiné) počítači mít, aby ses dostala k příponě\nnebo ke jménům nadřazených adresářů.</p>\n<div class=\"admonition note\"><p>Dokonce si můžeš vyzkoušet, jak by to fungovalo na jiném systému – místo <code>Path</code>\nnaimportuj a použij <code>PureWindowsPath</code> nebo <code>PurePosixPath</code>, které reprezentují\nWindowsové, resp. Unixové cesty.</p>\n</div><p>Zamysli se: k čemu se hodí umět pojmenovat soubor, který neexistuje?</p>\n<div class=\"solution\" id=\"solution-0\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/brno-podzim-pondeli/intro/pathlib/index/solutions/0/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>Jméno potřebuješ třeba když chceš soubor vytvořit.</p>\n </div>\n</div><p>Teď se dostaneme k operacím pro které je potřeba mít přístup k souborovému\nsystému.</p>\n<p>Nejdříve dvě funkce, které vrací cesty k užitečným adresářům:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"c1\"># Aktuální adresář</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">()</span>\n<span class=\"go\">PosixPath('/home/janca/pyladies/barvy')</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Můj domovský adresář</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">home</span><span class=\"p\">()</span>\n<span class=\"go\">PosixPath('/home/janca')</span>\n</pre></div><p>A základní otázky – existuje daný soubor?\nJe to normální soubor nebo adresář?</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"c1\"># Existuje na té ukázkové cestě nějaký soubor?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">exists</span><span class=\"p\">()</span>\n<span class=\"go\">False</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Existuje můj domovský adresář?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">home</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">exists</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># A je to vůbec adresář?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">home</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">is_dir</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Je to normální datový soubor?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">home</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">()</span>\n<span class=\"go\">False</span>\n</pre></div><h2>Ukázka</h2>\n<p>Abychom měli všichni stejné podmínky, stáhni si na další experimenty\n<a href=\"/2019/brno-podzim-pondeli/intro/pathlib/static/archiv.tar.gz\">archiv s testovacími soubory</a>.\nDej si ho do aktuálního adresáře (<code>Path.cwd()</code>), a pak ho rozbal pomocí\n<code>tarfile</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"kn\">import</span> <span class=\"nn\">tarfile</span>\n\n<span class=\"gp\">>>> </span><span class=\"n\">cesta_k_archivu</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s2\">"archiv.tar.gz"</span><span class=\"p\">)</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Co je v archivu?</span>\n<span class=\"gp\">>>> </span><span class=\"n\">tarfile</span><span class=\"o\">.</span><span class=\"n\">open</span><span class=\"p\">(</span><span class=\"n\">cesta_k_archivu</span><span class=\"p\">,</span> <span class=\"s1\">'r|gz'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">getnames</span><span class=\"p\">()</span>\n<span class=\"go\">['soubory',</span>\n<span class=\"go\"> 'soubory/hrad.jpeg',</span>\n<span class=\"go\"> 'soubory/hrad.attribution',</span>\n<span class=\"go\"> 'soubory/.gitignore',</span>\n<span class=\"go\"> 'soubory/kolecko.png',</span>\n<span class=\"go\"> 'soubory/texty',</span>\n<span class=\"go\"> 'soubory/texty/vodnik.txt',</span>\n<span class=\"go\"> 'soubory/texty/lidove',</span>\n<span class=\"go\"> 'soubory/texty/lidove/pes.txt',</span>\n<span class=\"go\"> 'soubory/texty/lidove/holka.txt',</span>\n<span class=\"go\"> 'soubory/texty/vladimir.txt',</span>\n<span class=\"go\"> 'soubory/texty/cizojazycne',</span>\n<span class=\"go\"> 'soubory/texty/cizojazycne/iroha.txt',</span>\n<span class=\"go\"> 'soubory/texty/cizojazycne/witch.txt',</span>\n<span class=\"go\"> 'soubory/hlad.txt',</span>\n<span class=\"go\"> 'soubory/hraz.attribution',</span>\n<span class=\"go\"> 'soubory/ententyky.txt',</span>\n<span class=\"go\"> 'soubory/hraz.jpeg',</span>\n<span class=\"go\"> 'soubory/README']</span>\n\n<span class=\"gp\">>>> </span><span class=\"c1\"># Extrakce archivu. (Kdybys to zkoušel/a pro jiné archivy, vždy před</span>\n<span class=\"gp\">>>> </span><span class=\"c1\"># rozbalením zkontroluj cesty všech souborů v archivu -- ať se rozbalením</span>\n<span class=\"gp\">>>> </span><span class=\"c1\"># nepřepíše nějaký důležitý soubor!)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">tarfile</span><span class=\"o\">.</span><span class=\"n\">open</span><span class=\"p\">(</span><span class=\"n\">cesta_k_archivu</span><span class=\"p\">,</span> <span class=\"s1\">'r|gz'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">extractall</span><span class=\"p\">()</span>\n</pre></div><p>Rozbalením archivu vznikl <code>./soubory/</code> (tedy: adresář <code>soubory</code> v aktuálním\nadresáři).\nPojď se mu kouknout na zoubek:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">zaklad</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"s1\">'./soubory'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">zaklad</span>\n<span class=\"go\">PosixPath('soubory')</span>\n\n<span class=\"gp\">>>> </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Je to adresář?'</span><span class=\"p\">,</span> <span class=\"n\">zaklad</span><span class=\"o\">.</span><span class=\"n\">is_dir</span><span class=\"p\">())</span>\n<span class=\"go\">Je to adresář? True</span>\n<span class=\"gp\">>>> </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Je to normální soubor?'</span><span class=\"p\">,</span> <span class=\"n\">zaklad</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">())</span>\n<span class=\"go\">Je to normální soubor? False</span>\n</pre></div><p>Podle informací o archivu je v soubory nějaký <code>ententyky.txt</code> – podle přípony\nsoubor s textem.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">ententyky</span> <span class=\"o\">=</span> <span class=\"n\">zaklad</span> <span class=\"o\">/</span> <span class=\"s1\">'ententyky.txt'</span>\n<span class=\"gp\">>>> </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Je to adresář?'</span><span class=\"p\">,</span> <span class=\"n\">ententyky</span><span class=\"o\">.</span><span class=\"n\">is_dir</span><span class=\"p\">())</span>\n<span class=\"go\">Je to adresář? False</span>\n<span class=\"gp\">>>> </span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Je to normální soubor?'</span><span class=\"p\">,</span> <span class=\"n\">ententyky</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">())</span>\n<span class=\"go\">Je to normální soubor? True</span>\n</pre></div><p>Objekty <code>Path</code> lze používat v naprosté většině situací, kdy jde použít cesta\njako řetězec.\nNapříklad pro funkci <code>open</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">with</span> <span class=\"nb\">open</span><span class=\"p\">(</span><span class=\"n\">ententyky</span><span class=\"p\">,</span> <span class=\"n\">encoding</span><span class=\"o\">=</span><span class=\"s1\">'utf-8'</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"nb\">file</span><span class=\"p\">:</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"nb\">file</span><span class=\"o\">.</span><span class=\"n\">read</span><span class=\"p\">())</span>\n</pre></div><p><code>Path</code> ale má <code>open</code> i jako metodu:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">with</span> <span class=\"n\">ententyky</span><span class=\"o\">.</span><span class=\"n\">open</span><span class=\"p\">(</span><span class=\"n\">encoding</span><span class=\"o\">=</span><span class=\"s1\">'utf-8'</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"nb\">file</span><span class=\"p\">:</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"nb\">file</span><span class=\"o\">.</span><span class=\"n\">read</span><span class=\"p\">())</span>\n</pre></div><p>A protože je čtení celého textového obsahu souboru docela užitečné,\nexistuje i zkratka která soubor otevře, přečte a zavře najednou:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">ententyky</span><span class=\"o\">.</span><span class=\"n\">read_text</span><span class=\"p\">())</span>\n</pre></div><p>(Větší soubory je ale lepší otevřít ve <code>with</code> a zpracovávat třeba po řádcích,\naby se obsah nemusel do paměti počítače načíst celý najednou.)</p>\n<p>Existuje i <code>write_text</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">cesta</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"s1\">'pisnicka.txt'</span>\n<span class=\"n\">cesta</span><span class=\"o\">.</span><span class=\"n\">write_text</span><span class=\"p\">(</span><span class=\"s1\">'Holka modrooká</span><span class=\"se\">\\n</span><span class=\"s1\">Nesedávej u potoka!'</span><span class=\"p\">)</span>\n</pre></div><h2>A co adresáře?</h2>\n<p>I s adresáři umí <code>pathlib</code> pracovat.\nNejzákladnější operace je získání cest k obsaženým souborům:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">zaklad</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">()</span>\n<span class=\"go\"><generator object Path.iterdir at 0x7fbd4443b9e8></span>\n</pre></div><p>Metoda iterdir opět vrací <em>iterátor</em> – objekt, přes který musíš „projít“\n(cyklem for, převedením na seznam ap.), abys z něj dostala obsah.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">zaklad</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">())</span>\n<span class=\"go\">[PosixPath('soubory/hrad.jpeg'),</span>\n<span class=\"go\"> PosixPath('soubory/hrad.attribution'),</span>\n<span class=\"go\"> PosixPath('soubory/.gitignore'),</span>\n<span class=\"go\"> PosixPath('soubory/kolecko.png'),</span>\n<span class=\"go\"> PosixPath('soubory/texty'),</span>\n<span class=\"go\"> PosixPath('soubory/hlad.txt'),</span>\n<span class=\"go\"> PosixPath('soubory/hraz.attribution'),</span>\n<span class=\"go\"> PosixPath('soubory/ententyky.txt'),</span>\n<span class=\"go\"> PosixPath('soubory/hraz.jpeg'),</span>\n<span class=\"go\"> PosixPath('soubory/README')]</span>\n\n<span class=\"gp\">>>> </span><span class=\"k\">for</span> <span class=\"n\">cesta</span> <span class=\"ow\">in</span> <span class=\"n\">zaklad</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">():</span>\n<span class=\"gp\">>>> </span> <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">cesta</span><span class=\"p\">)</span>\n<span class=\"go\">soubory/hrad.jpeg</span>\n<span class=\"go\">soubory/hrad.attribution</span>\n<span class=\"go\">soubory/.gitignore</span>\n<span class=\"go\">soubory/kolecko.png</span>\n<span class=\"go\">soubory/texty</span>\n<span class=\"go\">soubory/hlad.txt</span>\n<span class=\"go\">soubory/hraz.attribution</span>\n<span class=\"go\">soubory/ententyky.txt</span>\n<span class=\"go\">soubory/hraz.jpeg</span>\n<span class=\"go\">soubory/README</span>\n</pre></div><h2>Strom adresářů – rekurze</h2>\n<p>Adresáře, podadresáře a soubory v nich tvoří strukturu, na kterou se často\npoužívají rekurzivní funkce.</p>\n<p>Tady je funkce <code>vypis_soubory</code>, která ypíše všechny soubory v daném adresáři.\nPřed každé jméno dá odrážku <code>-</code>, aby to líp vypadalo:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">vypis_soubory</span><span class=\"p\">(</span><span class=\"n\">odrazka</span><span class=\"p\">,</span> <span class=\"n\">adresar</span><span class=\"p\">):</span>\n <span class=\"sd\">"""Vypíše odrážkový seznam jmen souborů v daném adresáři"""</span>\n <span class=\"k\">for</span> <span class=\"n\">soubor</span> <span class=\"ow\">in</span> <span class=\"n\">adresar</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">():</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">odrazka</span><span class=\"p\">,</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">name</span><span class=\"p\">)</span>\n\n<span class=\"n\">vypis_soubory</span><span class=\"p\">(</span><span class=\"s1\">'-'</span><span class=\"p\">,</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">())</span>\n</pre></div><p>Odrážka se dá zadat:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">vypis_soubory</span><span class=\"p\">(</span><span class=\"s1\">'*'</span><span class=\"p\">,</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">())</span>\n<span class=\"n\">vypis_soubory</span><span class=\"p\">(</span><span class=\"s1\">' *'</span><span class=\"p\">,</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">())</span>\n</pre></div><p>Tahle funkce se dá změnit, aby vypsala i obsahy <em>podadresářů</em>.\nJak?\nPoté, co vypíše jméno nějakého podadresáře, zavolá funkci která vypíše\nobsah toho podadresáře.\nTakovou funkci ale už máš napsanou – stačí trochu změnit odrážku, aby bylo\npoznat co je podadresář.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">vypis_soubory</span><span class=\"p\">(</span><span class=\"n\">odrazka</span><span class=\"p\">,</span> <span class=\"n\">adresar</span><span class=\"p\">):</span>\n <span class=\"sd\">"""Vypíše odrážkový seznam jmen souborů v daném adresáři i podadresářích"""</span>\n <span class=\"k\">for</span> <span class=\"n\">soubor</span> <span class=\"ow\">in</span> <span class=\"n\">adresar</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">():</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">odrazka</span><span class=\"p\">,</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">name</span><span class=\"p\">)</span>\n <span class=\"k\">if</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">is_dir</span><span class=\"p\">():</span>\n <span class=\"n\">vypis_soubory</span><span class=\"p\">(</span><span class=\"s1\">' '</span> <span class=\"o\">+</span> <span class=\"n\">odrazka</span><span class=\"p\">,</span> <span class=\"n\">soubor</span><span class=\"p\">)</span>\n\n<span class=\"n\">vypis_soubory</span><span class=\"p\">(</span><span class=\"s1\">'-'</span><span class=\"p\">,</span> <span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">())</span>\n</pre></div><p>Podobně lze například spočítat soubory v nějakém adresáři (i všech\npodadresářích).</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">pathlib</span> <span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">spocitej_normalni_soubory</span><span class=\"p\">(</span><span class=\"n\">adresar</span><span class=\"p\">):</span>\n <span class=\"sd\">"""Vrátí počet normálních souborů v daném adresáři i všech podadresářích"""</span>\n <span class=\"n\">pocet</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n <span class=\"k\">for</span> <span class=\"n\">soubor</span> <span class=\"ow\">in</span> <span class=\"n\">adresar</span><span class=\"o\">.</span><span class=\"n\">iterdir</span><span class=\"p\">():</span>\n <span class=\"k\">if</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">is_dir</span><span class=\"p\">():</span>\n <span class=\"n\">pocet</span> <span class=\"o\">=</span> <span class=\"n\">pocet</span> <span class=\"o\">+</span> <span class=\"n\">spocitej_normalni_soubory</span><span class=\"p\">(</span><span class=\"n\">soubor</span><span class=\"p\">)</span>\n <span class=\"k\">elif</span> <span class=\"n\">soubor</span><span class=\"o\">.</span><span class=\"n\">is_file</span><span class=\"p\">():</span>\n <span class=\"n\">pocet</span> <span class=\"o\">=</span> <span class=\"n\">pocet</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n <span class=\"k\">return</span> <span class=\"n\">pocet</span>\n\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">spocitej_normalni_soubory</span><span class=\"p\">(</span><span class=\"n\">Path</span><span class=\"o\">.</span><span class=\"n\">cwd</span><span class=\"p\">()))</span>\n</pre></div>\n\n\n " } } }