načítání...
nákupní košík
Košík

je prázdný
a
b

Python 3 - Mark Summerfield

-15%
sleva

Kniha: Python 3
Autor:

Chcete se odlišit od davů dalších programátorů a zvolili jste Python jako prostředek? Výukový kurz vám nabídne široký záběr témat věnovaných poslednímu evolučnímu stupni Pythonu, ...
Titul doručujeme za 3 pracovní dny
Vaše cena s DPH:  690 Kč 586
+
-
rozbalKdy zboží dostanu
19,5
bo za nákup
rozbalVýhodné poštovné: 29Kč
rozbalOsobní odběr zdarma

ukázka z knihy ukázka

Titul je dostupný ve formě:
tištěná forma elektronická forma

hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2%hodnoceni - 71.2% 90%   celkové hodnocení
1 hodnocení + 0 recenzí

Specifikace
Nakladatelství: » Computer press
Rok vydání: 2010-04-29
Počet stran: 584
Rozměr: 167 x 225 mm
Úprava: 584 stran
Vydání: Vyd. 1.
Název originálu: Programming in Python 3
Spolupracovali: překlad Lukáš Krejčí
Vazba: brožovaná lepená
ISBN: 9788025127377
EAN: 9788025127377
Ukázka: » zobrazit ukázku
Popis

Chcete se odlišit od davů dalších programátorů a zvolili jste Python jako prostředek? Výukový kurz vám nabídne široký záběr témat věnovaných poslednímu evolučnímu stupni Pythonu, se kterým zvládnete vyřešit drtivou většinu obvyklých zadání. Pronikněte i vy do světa krátkých a efektivních programů. Zkušený autor vás provede Pythonem od prvních jednoduchých programů až po komplexní projekty, které pracují se sítí, databázemi nebo ve více vláknech. Pro rychlé osvojení nových informací jsou v knize odkazy na podobná témata, která souvisejí s aktuálně probíranou látkou. Na konci každé kapitoly najdete příklady, krátké shrnutí a cvičení, které pomůže upevnit nově nabyté poznatky. Publikace vás mimo jiné naučí, jak: - Vytvářet vlastní balíčky a moduly - Zpracovávat soubory různých typů - Rozložit zátěž do procesů a vláken - Využít spolupráci s databázemi - Efektivně ladit a testovat vyvíjené projekty - Využít v programech sílu regulárních výrazů - Vytvořit grafické uživatelské rozhraní O autorovi: Mark Summerfield je nezávislý školitel a konzultant specializující se na Python, C++, Qt a PyQt. Je autorem a spoluautorem několika programátorských knih zaměřených na jazyky, které vyučuje. (výukový kurz)

Předmětná hesla
Python (programovací jazyk)
Programování
Kniha je zařazena v kategoriích
Mark Summerfield - další tituly autora:
Python 3 Python 3
Summerfield, Mark
Cena: 366 Kč
 
Recenze a komentáře k titulu
Zatím žádné recenze.


Ukázka / obsah
Přepis ukázky

LEKCE 5
Moduly
V této lekci:
Moduly a balíčky
Přehled standardní knihovny Pythonu
‹
‹





194
Lekce 5: Moduly
Zatímco pomocí funkcí můžeme rozdělit části kódu tak, aby je bylo možné opětovně použít v rámci
daného programu, moduly poskytují prostředky pro shromažďování skupin funkcí (a jak uvidíme
v následující lekci také vlastních datových typů) tak, aby je bylo možné použít v libovolném počtu
programů. Python dále nabízí možnost vytvářet balíčky, což jsou skupiny modulů seskupené
dohromady, obvykle z toho důvodu, že tyto moduly poskytují související funkční prvky, nebo proto, že na
sobě vzájemně závisejí.
První část této lekce popisuje syntaxe pro importování funkčních prvků z modulů a balíčků, ať už
se standardní knihovny nebo z našich vlastních modulů a balíčků. Ve druhé části se posuneme dále
a podíváme se, jak vytvářet vlastní balíčky a moduly. Ukážeme si dva vlastní moduly, z nichž první
bude seznamovací a druhý bude demonstrovat, jak vyřešit řadu praktických problémů, jako je
nezávislost na platformě a testování.
Druhá část nabízí stručný přehled standardní knihovny Pythonu. Je důležité mít na paměti, co tato
knihovna obsahuje, protože používání předem definovaných funkčních prvků značně zrychluje
programování. Mnohé moduly standardní knihovny je široce rozšířené, dobře otestované a
robustní. Kromě přehledu si pomocí malých příkladů ukážeme několik běžných případů užití. U modulů
probíraných v jiných lekcích budou navíc uvedeny křížové odkazy.
Moduly a balíčky
Modul jazyka Python je jednoduše řešeno soubor s příponou .py. Modul může obsahovat libovolný
kód jazyka Python. Všechny programy, které jsme dosud napsali, byly obsažené v jediném souboru
.py, a proto se jedná o moduly i programy. Podstatným rozdílem je to, že programy jsou navržené
pro spouštění, kdežto moduly jsou navržené pro importování a použití v programech.
Ne všechny moduly mají přidružené soubory .py. Například modul sys je vestavěný do Pythonu
a některé moduly jsou napsané v jiných jazycích (povětšinou v jazyku C). Nicméně větší část
knihovny Pythonu je napsána v jazyku Python. Pokud tedy například napíšeme import collections,
můžeme voláním collections.namedtuple() vytvářet pojmenované n-tice a funkčnost, k níž
přistupujeme, se nachází v souboru modulu collections.py. Z hlediska našeho programu je
nepodstatné, ve kterém jazyku je daný modul napsán, protože všechny moduly se importují a používají
stejným způsobem.
Pro importování lze použít několik syntaxí:
import importovatelný_prvek
import importovatelný_prvek1, importovatelný_prvek2, ..., importovatelný_prvekN
import importovatelný_prvek as preferovaný_název
Zde je importovatelný_prvek obvykle modulem, jako je collections, může však jít také o balíček
nebo modul v balíčku, přičemž se každá část odděluje tečkou (.), například os.path. První dvě
syntaxe používáme v rámci této knihy. Jsou nejjednodušší a také nejbezpečnější, protože nehrozí
možnost konfliktu názvů, což je dáno tím, že musíme vždy používat plně kvalifikované názvy.
Webová doku-
mentace
¾ 171
Balíčky
¾ 197





195
Třetí syntaxe nám umožňuje dát importovanému balíčku nebo modulu název dle vlastní volby. To
sice může teoreticky vést ke kolizi názvů, ovšem v praxi se tato syntaxe používá právě proto, aby k ní
nedocházelo. Přejmenování je užitečné zejména tehd y, když experimentujeme s různými
implementacemi nějakého modulu. Pokud máme například dva moduly MyModuleA a MyModuleB, které mají
stejné rozhraní API (Application Programming Interface – aplikační programovací rozhraní), mohli
bychom v programu napsat import MyModuleA as MyModule a později hladce přejít k druhému
modulu příkazem import MyModuleB as MyModule.
Kde bychom měli příkazy import umisťovat? Běžně se všechny příkazy import umisťují na začátek
souborů .py, za řádek shebang a před dokumentaci modulu. Jak jsme si již řekli v lekci 1,
doporučujeme nejdříve importovat moduly standardní knihovny, poté moduly knihoven třetích stran a
nakonec naše vlastní moduly.
Zde je několik dalších syntaxí příkazu import:
from importovatelný_prvek import objekt as preferovaný_název
from importovatelný_prvek import objekt1, objekt2, ..., objektN
from importovatelný_prvek import (objekt1, objekt2, objekt3, objekt4, objekt5,
objekt6, ..., objektN)
from importovatelný_prvek import *
Tyto syntaxe mohou způsobovat konflikty názvů, poněvadž činí importované objekty (proměnné,
funkce, datové typy nebo moduly) přímo přístupné. Pokud chceme použít syntaxi from ... import
pro importování velkého množství objektů, můžeme použít více řádků, a to buď tak, že každý nový
řádek kromě posledního potlačíme nebo názvy objektů uzavřeme do závorek, jak ukazuje třetí
syntaxe.
Hvězdička (*) v poslední syntaxi znamená „importuj vše, co není soukromé“, což v praxi znamená
buď to, že se importuje každý objekt v modulu kromě těch, jejichž název začíná podtržítkem, nebo
že se importují všechny objekty, jejichž názvy jsou obsaženy v seznamu __all__ definovaném jako
globální proměnná daného modulu.
Zde je několik příkladů použití příkazu import:
import os
print(os.path.basename(filename)) # bezpečný, plně kvalifikovaný přístup
import os.path as path
print(path.basename(filename)) # riziko kolize názvů s path
from os import path
print(path.basename(filename)) # riziko kolize názvů s path
from os.path import basename
print(basename(filename)) # riziko kolize názvů s basename
from os.path import *
print(basename(filename)) # riziko kolize spousty názvů
__all__
¾ 198
Moduly a balíčky





196
Lekce 5: Moduly
Syntaxe from importovatelný_prvek import * importuje všechny objekty z daného modulu (nebo
všechny moduly z daného balíčku), což může znamenat stovky názvů. V případě příkazu from os.path
import * se importuje téměř 40 názvů, mezi něž patří i dirname, exists a split, což mohou být
názvy, které bychom raději použili pro naše vlastní proměnné nebo funkce.
Pokud například napíšeme příkaz from os.path import dirhame, pak můžeme přímo zavolat
dirname() bez kvalifikace. Pokud poté ale ve svém kódu napíšeme dirname = „.“, bude nyní odkaz
na objekt dirname místo funkce dirname() svázán s řetězcem “.”, takže když se pokusíme zavolat
dirname(), obdržíme výjimku TypeError, protože dirname nyní ukazuje na řetězec a řetězce nejsou
volatelné.
Z hlediska případných kolizí názvů vytvářených syntaxí import * některé vývojářské týmy
specifikují ve svých směrnicích, že se může používat pouze syntaxe import importovatelný_prvek.
Nicméně určité rozsáhlé balíčky, zvláště pak knihovny GUI, se často importují tímto způsobem,
protože obsahují obrovské množství funkcí a tříd (vlastních datových typů), jejichž ruční vypisování
by bylo velice pracné.
Přirozeně zde vyvstává otázka, jak Python ví, kde importované moduly a balíčky hledat?
Vestavěný modul sys obsahuje seznam sys.path, který uchovává seznam adresářů, které představují cestu
Pythonu (Python path). První adresář je adresářem, který obsahuje samotný program, a to i tehdy,
pokud byl program vyvolán z jiného adresáře. Je-li nastavena proměnná prostředí PYTHONPATH,
jsou v ní specifikované další cesty v seznamu. Poslední cesty jsou ty, které jsou nezbytné pro přístup
k standardní knihovně Pythonu – nastavují se při instalaci Pythonu.
Upozornění: Při prvním importu vestavěného modulu se Python po tomto modulu podívá
postupně v každé cestě uvedené v seznamu sys.path. Jedním z důsledků tohoto postupu je
to, že pokud vytvoříme modul nebo program se stejným názvem, jako má jeden z knihovních
modulů Pythonu, najde se ten náš jako první, což nevyhnutelně způsoby problémy. Aby k
tomuto nedošlo, nikdy nevytvářejte program či modul se stejný názvem, jako má některý z knihovních
adresářů či modulů Pythonu nejvyšší úrovně. Výjimkou je samozřejmě situace, kdy vytváříte svou
vlastní implementaci takovéhoto modulu a záměrně jej přepisujete. (Modul nejvyšší úrovně je
modul, jehož soubor .py je umístěn v jednom z adresářů v cestě Pythonu, a ne v jednom z jejich
podadresářů.) Například v systému Windows obsahuje cesta Pythonu obvykle adresář s názvem
C:Python31Lib, takže na této platformě bychom neměli vytvářet modul s názvem Lib.py
ani modul se stejným názvem, jako má kterýkoliv modul v adresáři C:Python31Lib.
Pro rychlý způsob kontroly, zda se nějaký název modulu již používá, stačí vyzkoušet příkaz import
s tímto názvem. To lze provést v konzole zavoláním interpretu s volbou příkazového řádku –c
(„execute code“ – proveď kód), za níž umístíme příslušný příkaz import. Pokud například chceme
zjistit, zda existuje modul s názvem Music.py (nebo adresář nejvyšší úrovně v cestě Pythonu s názvem
Music), pak můžeme do konzoly napsat následující příkaz:
python -c „import Music“
Pokud obdržíme výjimku ImportError, víme, že se žádný modul nebo adresář nejvyšší úrovně
tohoto jména nepoužívá. Jakýkoliv jiný výstup (nebo žádný) znamená, že toto jméno je již zabráno. Tento
postup ale naneštěstí nezaručuje, že daný název bude vždy bez problémů, poněvadž můžeme později
nainstalovat balíček či modul Pythonu od třetí strany, který obsahuje konfliktní název, i když v praxi
se jedná o velmi ojedinělý problém.





197
Pokud bychom například vytvořili soubor modulu s názvem os.py, došlo by ke konfliktu s
knihovním modulem os. Pokud ale vytvoříme modul s názvem path.py, bude to v pořádku, protože bude
importován jako modul path, kdežto knihovní modul se importuje jako os.path. V této knize je
v názvech souborů našich vlastních modulů první písmeno vždy velké, čímž se vyhneme
konfliktům názvů (alespoň na Unixu), protože názvy souborů modulů standardní knihovny obsahují jen
malá písmena.
Program může importovat některé moduly, které následně importují své vlastní moduly, včetně
některých, které již byly importovány. To však nezpůsobí žádné problémy. Kdykoliv je totiž nějaký
modul importován, tak Python nejdříve zkontroluje, zda již nebyl importován dříve. Pokud nebyl,
tak Python spustí zkompilovaný bajt-kód modulu, čímž vytvoří příslušné proměnné, funkce a další
objekty daného modulu a interně si poznačí, že tento modul již byl importován. Při každém dalším
importu tohoto modulu Python detekuje, že již byl importován, a neudělá nic.
Když Python potřebuje zkompilovaný bajt-kód modulu, automaticky jej vygeneruje. Tím se liší třeba
od Javy, kde se kompilace do bajt-kódu musí provést explicitním způsobem. Python se nejdříve
podívá po souboru se stejným názvem jako má soubor .py daného modulu, ale s příponou .pyo, což je
optimalizovaná verze se zkompilovaným bajt-kódem modulu. Pokud žádný soubor .pyo neexistuje
(nebo pokud je starší než soubor .py, což znamená, že není aktuální), Python se podívá po
souboru s příponou .pyc, což je neoptimalizovaná verze se zkompilovaným bajt-kódem modulu. Pokud
Python najde aktuální verzi se zkompilovaným bajt-kódem modulu, tak ji načte. V opačném případě
načte soubor .py a zkompiluje verzi se zkompilovaným bajt-kódem. Tak jako tak bude mít nakonec
Python modul v paměti ve formě zkompilovaného bajt-kódu.
Pokud by Python musel zkompilovat soubor .py, uloží jej do souboru .pyc (nebo .pyo, pokud je na
příkazovém řádku uvedena volba -O nebo pokud je nastavena proměnná prostředí
PYTHONOPTIMIZE), ovšem za předpokladu, že do příslušného adresáře lze zapisovat. Ukládání bajt-kódu lze zamezit
volbou příkazového řádku -B nebo nastavením proměnné prostředí PYTHONDONTWRITEBYTECODE.
Používání souborů se zkompilovaným bajt-kódem vede k rychlejšímu spouštění, protože interpret
nemusí kód načítat, kompilovat, ukládat (je-li to možné) a spouštět, ale stačí mu jen kód načíst a
spustit. Je však třeba poznamenat, že na samotný běh kódu to žádný vliv nemá. Při instalaci Pythonu se
moduly standardní knihovny obvykle zkompilují do bajt-kódu v rámci instalačního procesu.
Balíčky
Balíček je obyčejným adresářem, který obsahuje skupinu modulů a soubor s názvem __init__.py.
Představte si, že máme smyšlenou skupinu souborů modulů pro čtení a zapisování nejrůznějších
formátů grafických souborů, jako jsou například moduly Bmp.py, Jpeg.py, Png.py, Tiff.py a Xpm.
py, z nichž každý nabízí funkce load(), save() a tak podobně.
*
Moduly bychom mohli nechat ve
stejném adresáři, v němž je náš program, ale u větších programů, které používají množství vlastních
modulů, by se grafické moduly úplně ztratily. Jejich umístěním do samostatného podadresáře (např.
Graphics) je budeme mít pěkně pohromadě. A pokud k nim do adresáře Graphics přidáme
prázdný soubor __init__.py, stane se z tohoto adresáře balíček:
* Rozsáhlou podporu pro práci s grafickými soubory poskytuje spousta modulů třetích stran, z nichž je
nejpozoruhodnější knihovna Python Imaging Library (www.pythonware.com/products/pil).
Moduly a balíčky





198
Lekce 5: Moduly
Graphics/
__init__.py
Bmp.py
Jpeg.py
Png.py
Tiff.py
Xpm.py
Dokud bude adresář Graphics podadresářem uvnitř adresáře našeho programu nebo bude uveden
v cestě Pythonu, můžeme libovolný z těchto modulů importovat a používat. Musíme ale myslet na
to, aby název zastřešujícího modulu (Graphics) nebyl stejný jako kterýkoliv z názvů nejvyšší úrovně
ve standardní knihovně, jinak by došlo ke konfliktu názvů. (Na systému Unix stačí, když budou mít
názvy našich modulů první písmeno velké, neboť všechny moduly standardní knihovny mají názvy
s malými písmeny.) Náš modul můžeme importovat a používat takto:
import Graphics.Bmp
image = Graphics.Bmp.load(“bashful.bmp”)
U krátkých programů můžeme používat kratší názvy, což lze v Pythonu provést dvěma malinko
odlišnými způsoby.
import Graphics.Jpeg as Jpeg
image = Jpeg.load(“doc.jpeg”)
Zde jsme importovali modul Jpeg z balíčku Graphics a řekli jsme Pythonu, že se na něj chceme místo
plně kvalifikovaného jména Graphics.Jpeg odkazovat jen jako na Jpeg.
from Graphics import Png
image = Png.load(“dopey.png”)
V tomto úryvku kódu importujeme modul Png přímo z balíčku Graphics. Při použití této syntaxe
(from ... import) je modul Png přímo přístupný. Nikdo nás nenutí používat v našem kódu názvy
používané v balíčku:
from Graphics import Tiff as picture
image = picture.load(“grumpy.tiff”)
Zde používáme modul Tiff, který jsme ale ve svém programu přejmenovali na modul picture.
V některých situacích je výhodné načíst všechny moduly balíčku pomocí jediného příkazu. K tomu
je nutné upravit soubor __init__.py daného balíčku tak, aby obsahoval příkaz, který stanoví, které
moduly se mají načíst. Tento příkaz musí přiřadit seznam názvů modulů do speciální proměnné __
all__. Zde je například požadovaný řádek pro soubor Graphics/__init__.py:
__all__ = [„Bmp“, „Jpeg“, „Png“, „Tiff“, „Xpm“]
Nic víc není třeba, i když do souboru __init__.py samozřejmě můžeme umístit libovolný další kód.
Nyní můžeme použít další typ příkazu import:





199
from Graphics import *
image = Xpm.load(„sleepy.xpm“)
Syntaxe from balíček import * přímo importuje všechny moduly uvedené v seznamu __all__. Po
provedení tohoto příkazu je přímo přístupný nejen modul Xpm, ale také všechny ostatní moduly.
Jak jsme si řekli již dříve, tuto syntaxi lze aplikovat také na modul (tj. from modul import *) při
tom se importují všechny funkce, proměnné a další objekty definované v zadaném modulu (kromě
těch, jejichž název začíná podtržítkem). Pokud chceme mít kontrolu nad tím, co přesně se má při
použití syntaxe from modul import * importovat, můžeme definovat seznam __all__ i v
samotném modulu. V takovém případě importuje příkaz from modul import * pouze ty objekty, jejichž
názvy jsou uvedeny v seznamu __all__.
Dosud jsme si ukázali pouze jednu úroveň zanoření, Python nám však umožňuje vnořovat balíčky
tak hluboko, jak potřebujeme. Můžeme tak mít v adresáři Graphics třeba podadresář Vector a v něm
soubory modulů, například Eps.py a Svg.py:
Graphics/
__init__.py
Bmp.py
Jpeg.py
Png.py
Tiff.py
Vector/
__init__.py
Eps.py
Svg.py
Xpm.py
Adresář Vector se stane balíčkem v okamžiku, kdy do něj umístíme soubor __init__.py, a jak jsme
si již řekli, tento soubor může být prázdný nebo může obsahovat seznam __all__ pro potřeby
programátorů, kteří chtějí provést import pomocí příkazu from Graphics.Vector import *.
Pro přístup k vnořenému balíčku vycházíme ze syntaxe, kterou jsme již používali:
import Graphics.Vector.Eps
image = Graphics.Vector.Eps.load(“sneezy.eps”)
Plně kvalifikovaný název je poněkud delší, čemuž se snaží někteří programátoři zamezit tím, že se
snaží udržovat hierarchie svých modulů docela ploché.
import Graphics.Vector.Svg as Svg
image = Svg.load(“snow.svg”)
Pro modul můžeme vždy použít náš vlastní krátký název, jak jsme to provedli zde, i když se tím
vystavujeme vyššímu riziku konfliktu názvů.
Všechny importy, které jsme dosud používali (a které budeme používat i ve zbývající části knihy),
se označují jako absolutní importy, což znamená, že každý námi importovaný modul je v některém
Moduly a balíčky





200
Lekce 5: Moduly
z adresářů uvedených v proměnné sys.path (nebo podadresářů, pokud název v příkazu import
obsahuje jednu či více teček, které slouží v podstatě jako oddělovače v cestě). Při vytváření
rozsáhlých balíčků s více moduly a adresáři je často užitečné importovat další moduly, které jsou součástí
stejného balíčku. Například v souboru Eps.py nebo Svg.py můžeme získat přístup k modulu Png
pomocí konvenčního nebo relativního importu:
import Graphics.Png as Png from ..Graphics import Png
Tyto dva úryvky kódu jsou ekvivalentní, protože oba přímo zpřístupňují modul Png uvnitř modulu,
kde se používají. Všimněte si ale, že relativní importy, což jsou importy, které používají syntaxi from
modul import s tečkami před názvem modulu (každá tečka představuje jeden krok směrem nahoru
v hierarchii adresářů), můžeme použít pouze v modulech, které jsou uvnitř nějakého balíčku.
Relativní importy usnadňují přejmenování zastřešujícího balíčku a uvnitř balíčků zamezují nechtěnému
importování standardních modulů místo našich vlastních.
Vlastní moduly
Moduly jsou obyčejné soubory s příponou .py, a proto je lze vytvářet bez dalších formalit. V
této části se podíváme na dva naše vlastní moduly. První modul TextUtil (v souboru TextUtil.py)
obsahuje jen tři funkce: is_balanced(), která vrací hodnotu True, má-li zadaný řetězec vyvážené
závorky nejrůznějších druhů, shorten() (viz dříve – strana 175) a simplify(), která dokáže z
řetězce odříznout nežádoucí bílé místo a další znaky. Při probírání tohoto modulu se podíváme také na
to, jak spouštět kód v dokumentačních řetězcích jako testy jednotek.
Druhý modul CharGrid (v souboru CharGrid.py) uchovává znakovou mřížku a umožňuje do této
mřížky „kreslit“ čáry, obdélníky a text a celou mřížku vykreslit do konzoly. V tomto modulu si
ukážeme několik technik, se kterými jsme se dosud nesetkali a které jsou typické pro rozsáhlejší
a komplexnější moduly.
Modul TextUtil
Struktura tohoto modulu (a většiny dalších) se odlišuje od struktury programu. Prvním řádkem je
řádek shebang a poté zde máme komentáře (obvykle copyright a informace o licenci). Dále je
obvykle uváděn řetězec s trojitými uvozovkami, který poskytuje přehled obsahu modulu často doplněný
ukázkovými příklady – jedná se o dokumentační řetězec modulu. Zde je začátek souboru TextUtil.
py (ovšem bez řádků s informacemi o licenci):
#!/usr/bin/env python3
# Copyright (c) 2008-9 Qtrac Ltd. All rights reserved.
„““
Tento modul nabízí několik funkcí pro manipulaci s řetězci.
>>> is_balanced(“(Python (není (jako (lisp))))”)
True
>>> shorten(“Velká křižovatka”, 10)
‘Velká k...’





201
>>> simplify(“ nějaký text s nadbytečnými mezerami “)
‘nějaký text s nadbytečnými mezerami’
“””
import string
Dokumentační řetězec modulu je k dispozici programům (nebo dalším modulům), které tento modul
importují, jako TextUtil.__doc__. Za dokumentačním řetězcem modulu následují importy a poté
zbytek modulu.
Funkci shorten() jsme již viděli, a proto ji zde nebudeme opakovat. A protože se spíše než na
funkce zaměřujeme na moduly, ukážeme si kromě funkce simplify(), kterou si ukážeme celou včetně
dokumentačního řetězce, pouze kód funkce is_balanced().
Takto vypadá funkce simplify() rozdělená na dvě části:
def simplify(text, whitespace=string.whitespace, delete=““):
r“““Vrátí text s vícenásobnými mezerami zredukovanými do jediné mezery
Parametr whitespace je řetězec znaků, z nichž každý
je považován za mezeru.
Není-li parametr delete prázdný, měl by obsahovat řetězec, jehož
znaky se vyhledají ve výsledném řetězci a odstraní.
>>> simplify(“ tohle a také tamto”)
‘tohle a také tamto’
>>> simplify(“ Vejce a.s. ”)
‘Vejce a.s.’
>>> simplify(“ Vejce a.s. ”, delete=”,;:.”)
‘Vejce as’
>>> simplify(“ nesamohláskový “, delete=”aáeiouyý”)
‘nsmhlskv’
“””
Po řádku s příkazem def následuje dokumentační řetězec funkce se známou strukturou: na jednom
řádku popis, prázdný řádek, podrobnější popis a pak několik příkladů napsaných tak, jako by byly
zadávány interaktivně. Řetězce v uvozovkách jsou v dokumentačním řetězci, a proto je nutné buď
potlačit v nich uvedená zpětná lomítka, nebo dokumentační řetězec uzavřít do trojitých uvozovek,
což jsme udělali my.
result = []
word = „“
for char in text:
if char in delete:
continue
elif char in whitespace:
if word:
shorten()
¾ 175
Holé
řetězce
¾ 72
Moduly a balíčky





202
Lekce 5: Moduly
result.append(word)
word = „“
else:
word += char
if word:
result.append(word)
return „ „.join(result)
Seznam result používáme pro uchovávání „slov“, což jsou řetězce, jež nemají mezery nebo vyškrtnuté
znaky (parametr delete). Zadaný text procházíme po jednotlivých znacích, přičemž přeskakujeme
vyškrtnuté znaky. Narazíme-li na znak považovaný za bílé místo (parametr whitespace) a současně
vytváříme slovo (proměnná word), přidáme toto slovo do seznamu result a nastavíme jej na
prázdný řetězec. V opačném případě bílé místo přeskočíme. Jakýkoliv jiný znak přidáme do vytvářeného
slova. Nakonec vrátíme jediný řetězec všech slov v seznamu result spojených jedinou mezerou.
Funkce is_balanced() je zapsána podobným způsobem: nejdříve je řádek s příkazem def, poté
dokumentační řetězec s jednořádkovým popisem, prázdný řádek, podrobnější popis, několik
příkladů a pak samotný kód. Zde je kód bez dokumentačního řetězce:
def is_balanced(text, brackets=“()[]{}<>“):
counts = {}
left_for_right = {}
for left, right in zip(brackets[::2], brackets[1::2]):
assert left != right, “znaky závorek se musejí lišit”
counts[left] = 0
left_for_right[right] = left
for c in text:
if c in counts:
counts[c] += 1
elif c in left_for_right:
left = left_for_right[c]
if counts[left] == 0:
return False
counts[left] -= 1
return not any(counts.values())
V této funkci sestavujeme dva slovníky. Klíči slovníku counts jsou otevírací znaky („(“, „[“, „{“ a „<“)
a jeho hodnotami celá čísla. Klíči slovníku left_for_right jsou uzavírací znaky („)“, „]“, „}“ a „>“)
a jeho hodnotami odpovídající otevírací znaky. Jakmile jsou slovníky připraveny, procházíme text
znak po znaku. Jakmile narazíme na otevírací znak, zvýšíme odpovídající počítadlo (slovník counts).
A podobně, jakmile narazíme na uzavírací znak, vyhledáme odpovídající uzavírací znak. Je-li
počítadlo pro tento znak 0, znamená to, že jsme narazili na uzavírací znak bez odpovídajícího otevíracího
znaku, a proto okamžitě vrátíme hodnotu False. V opačném případě snížíme příslušné počítadlo.
Na konci by mělo mít každé počítadlo hodnotu 0, jsou-li všechny dvojice vyvážené, takže pokud je
některé z nich nenulové, funkce vrátí hodnotu False. Jinak vrátí hodnotu True.





203
Až dosud bylo vše podobné jako v kterémkoliv jiném souboru .py. Pokud by byl soubor TextUtil.
py programem, jistě by obsahoval několik dalších funkcí a na konci by bylo jediné volání některé
z těchto funkcí, které by zahájilo zpracování. Avšak vzhledem k tomu, že se jedná o modul, který má
být importován, jsou definované funkce dostačující. Nyní může libovolný program či modul
importovat modul TextUtil a používat jej:
import TextUtil
text = “ záhadný hlavolam “
text = TextUtil.simplify(text) # text == ‘záhadný hlavolam’
Pokud chceme modul TextUtil zpřístupnit určitému programu, musíme soubor TextUtil.py
umístit do stejného adresáře, ve kterém se nachází daný program. Pokud chceme modul TextUtil
zpřístupnit všem svým programům, pak máme k dispozici několik možností. Jednou z nich je umístit
modul do podadresáře s balíčky v rámci distribuce Pythonu. V systému Windows se obvykle jedná
o adresář C:Python31Libsite-packages, v případě systémů Mac OS X a Unix však může být jeho
umístění různé. Tento adresář se nachází v cestě Pythonu, takže libovolný v něm umístěný modul
bude vždy nalezen. Druhá možnost spočívá ve vytvoření adresáře speciálně pro náš vlastní modul,
který chceme používat ve všech svých programech, a v nastavení proměnné prostředí PYTHONPATH
na tento adresář. Třetí možností je umístit modul do lokálního podadresáře site-packages. Jedná
se o adresář, který je umístěn v cestě Pythonu a který má v systému Windows podobu %APPDATA%
PythonPython31site-packages a v systému Unix (včetně Mac OS X) podobu ~/.local/lib/
python3.1/site-packages. Druhá a třetí možnost má tu výhodu, že máme náš kód oddělený od
oficiální instalace.
Mít modul TextUtil je sice skvělé, ale pokud jej bude používat spousta programů, pak si chceme
být jisti, že funguje tak, jak je uvedeno. Jeden skutečně jednoduchý způsob spočívá v provedení
příkladů v dokumentačním řetězci a v kontrole, zda obdržíme očekávané výsledky. To můžeme provést
přidáním pouhých třech řádků na konec souboru .py tohoto modulu:
if __name__ == „__main__“:
import doctest
doctest.testmod()
Kdykoliv je nějaký modul importován, Python pro něj vytvoří proměnnou s názvem __name__ a uloží
název modulu do této proměnné. Název modulu je prostý název souboru .py bez přípony. V tomto
případě bude mít tedy proměnná __name__ po importu modulu hodnotu „TextUtil“, takže
podmínka if nebude splněna, a proto se poslední dva řádky neprovedou. To znamená, že tyto tři řádky
nemají prakticky žádný význam, je-li modul importován.
Kdykoliv je nějaký soubor .py spuštěn, Python pro něj vytvoří proměnnou s názvem __name__ a
nastaví ji na řetězec „__main__“. Pokud tedy spustíme soubor TextUtil.py jako by se jednalo o program,
Python nastaví proměnnou __name__ na hodnotu „__main__“ a podmínka if se vyhodnotí na True,
takže se poslední dva řádky provedou.
Funkce doctest.testmod() použije introspektivní prvky Pythonu pro vyhledání všech funkcí
v daném modulu a jejich dokumentačních řetězců a pokusí se provést všechny v nich umístěné
úryvky kódu. Když modul takto spustíme, obdržíme výstup pouze v případě výskytu nějakých chyb. To
Moduly a balíčky





204
Lekce 5: Moduly
může být na první pohled znepokojující, protože to vypadá, že se nic nestalo. Pokud ale na
příkazovém řádku předáme příznak -v, obdržíme výstup podobný následujícímu:
Trying:
is_balanced(“(Python (není (jako (lisp))))”)
Expecting:
True
ok
...
Trying:
simplify(“ nesamohláskový “, delete=”aáeiouyý”)
Expecting:
‘nsmhlskv’
ok
4 items passed all tests:
3 tests in __main__
5 tests in __main__.is_balanced
3 tests in __main__.shorten
4 tests in __main__.simplify
15 tests in 4 items.
15 passed and 0 failed.
Test passed.
Místo množství vynechaných řádků je uveden výpustek. Jsou-li v modulu funkce (nebo třídy či
metody), které nemají testy, pak jsou při použití volby -v taktéž uvedeny. Všimněte si, že modul doctest
nalezl testy v dokumentačním řetězci modulu i v dokumentačních řetězcích funkcí.
Příklady v dokumentačních řetězcích, které lze spouštět jako testy, se nazývají dokumentační testy
(doctests). Je třeba poznamenat, že při psaní dokumentačních testů můžeme zavolat funkci simplify()
a ostatní funkce bez nutnosti kvalifikace (k dokumentačním testům totiž dochází uvnitř
samotného modulu). Vně tohoto modulu musíme za předpokladu, že jsme použili příkaz import TextUtil,
používat kvalifikované názvy, například TextUtil.is_balanced().
V následující podčásti si ukážeme, jak provádět více důkladných testů – konkrétně testovací
případy, v nichž očekáváme selhání, například neplatná data způsobující výjimky. (Testování se budeme
podrobně věnovat v lekci 9.) Kromě toho se podíváme na několik dalších problémů, k nimž dochází
při vytváření modulu, jako je inicializace modulu, ohled na rozdíly mezi platformami a zajištění, aby
se při použití syntaxe from modul import * do programu či modulu skutečně importovaly pouze
ty objekty, které chceme zveřejnit.
Modul CharGrid
Modul CharGrid uchovává v paměti znakovou mřížku. Nabízí funkce pro „kreslení“ čar, obdélníků
a textu do mřížky a pro vykreslení této mřížky do konzoly. Zde jsou dokumentační testy z
dokumentačních řetězců:





205
>>> resize(14, 50)
>>> add_rectangle(0, 0, *get_size())
>>> add_vertical_line(5, 10, 13)
>>> add_vertical_line(2, 9, 12, „!“)
>>> add_horizontal_line(3, 10, 20, „+“)
>>> add_rectangle(0, 0, 5, 5, „%“)
>>> add_rectangle(5, 7, 12, 40, „#“, True)
>>> add_rectangle(7, 9, 10, 38, „ „)
>>> add_text(8, 10, „Tohle je náš modul CharGrid“)
>>> add_text(1, 32, “Pěkně odporný”, “@”)
>>> add_rectangle(6, 42, 11, 46, fill=True)
>>> render(False)
Funkce CharGrid.add_rectangle() přijímá nejméně čtyři argumenty: řádek a sloupec levého
horního rohu a řádek a sloupec pravého spodního rohu. Znak použitý pro nakreslení obrysu lze zadat
jako pátý argument a jako šestý argument logickou hodnotu signalizující, zda má být obdélník
vyplněn (stejným znakem jako obrys). Při prvním zavolání předáme třetí a čtvrté argumenty rozbalením
n-tice se dvěma prvky (šířka, výška) vrácené funkcí CharGrid.get_size().
Funkce CharGrid.render() ve výchozím nastavení vymaže obrazovku před vypsáním mřížky, čemuž
lze zamezit předáním hodnoty False, jak jsme zde učinili také my. Níže je uvedena mřížka, která je
výsledkem výše uvedených dokumentačních testů:
%%%%%*********************************************
% % @@@@@@@@@@@@@@@ *
% % @Pěkně odporný@ *
% % ++++++++++ @@@@@@@@@@@@@@@ *
%%%%% *
* ################################# *
* ################################# **** *
* ## ## **** *
* ## Tohle je náš modul CharGrid ## **** *
* ! ## ## **** *
* ! | ################################# **** *
* ! | ################################# *
* | *
**************************************************
Modul začíná stejným způsobem jako modul TextUtil: řádkem shebang, komentářem s copyrightem
a informacemi o licenci a dokumentačním řetězcem, který popisuje modul a obsahuje výše uvedené
dokumentační testy. Řádný kód pak začíná dvěma importy, z nichž prvním je modul sys a druhý
modul subprocess. Modulu subprocess se budeme věnovat v lekci 10.
Modul se řídí dvěma zásadami pro ošetření chyb. Několik funkcí definuje parametr char, jehož
aktuálním argumentem musí být vždy řetězec obsahující přesně jeden znak. Porušení tohoto požadavku
je považováno za fatální chybu programování, takže ke kontrole délky používáme příkazy assert.
Moduly a balíčky





206
Lekce 5: Moduly
Na druhou stranu předání čísla řádku či sloupce mimo rozsah je považováno za chybové, ale
normální, a proto dojde k vyvolání vlastní výjimky.
Nyní prostudujeme několik ilustrativních a klíčo vých částí kódu tohoto modulu, přičemž začneme
vlastními výjimkami:
class RangeError(Exception): pass
class RowRangeError(RangeError): pass
class ColumnRangeError(RangeError): pass
Žádná z funkcí v modulu, která vyvolává výjimku, nikdy nevyvolá chybu RangeError, ale vždy vyvolá
specifickou výjimku v závislosti na tom, zda hodnota zadaná mimo rozsah představuje řádek nebo
sloupec. Avšak tím, že používáme hierarchii, dáváme uživatelům modulu možnost zachytit
specifickou výjimku nebo zachytit kteroukoliv z nich zachycením bázové třídy RangeError. Všimněte si také,
že uvnitř dokumentačních testů používáme názvy výjimek tak, jak jsou zde uvedeny, ale při importu
modulu příkazem import CharGrid je samozřejmě nutné psát CharGrid.RangeError, CharGrid.
RowRangeError a CharGrid.ColumnRangeError.
_CHAR_ASSERT_TEMPLATE = („je nutné zadat jediný znak: ‘{0}‘ „
“je příliš dlouhý”)
_max_rows = 25
_max_columns = 80
_grid = []
_background_char = „ „
Zde definujeme několik soukromých dat pro interní použití v modulu. Identifikátory začínají
podtržítkem, takže pokud se modul importuje příkazem from CharGrid import *, neimportuje se žádná
z těchto proměnných. (Další možností by bylo zřízení seznamu __all__.) Řetězec _CHAR_ASSERT_
TEMPLATE se používá v souvislosti s metodou str.format() pro vytvoření chybové zprávy v příkazech
assert. K ostatním proměnným se vrátíme, jakmile se dostaneme k jejich použití v kódu.
if sys.platform.startswith(„win“):
def clear_screen():
subprocess.call([“cmd.exe”, “/C”, “cls”])
else:
def clear_screen():
subprocess.call([“clear”])
clear_screen.__doc__ = “””Vymaže obrazovku pomocí příkazu pro
vymazání obrazovky aktuálně používaného systému”””
Prostředek k vymazání obrazovky je nezávislý na platformě. V systému Windows musíme spustit
program cmd.exe s příslušnými argumenty a na většině unixových systémů spustíme program clear.
Funkce subprocess.call() modulu subprocess umožňuje spuštění externího programu, takže ji
můžeme použít k vymazání obrazovky způsobem vhodným pro používanou platformu. Řetězec
sys.platform uchovává název operačního systému, na kterém daný program běží (např. „win32“
nebo „linux2“). Jeden ze způsobů pro překlenutí rozdílů mezi platformami tedy spočívá v
definování jediné funkce:





207
def clear_screen():
command = ([“clear”] if not sys.platform.startswith(“win”) else
[“cmd.exe”, “/C”, “cls”])
subprocess.call(command)
Nevýhodou tohoto postupu je, že i když víme, že se platforma za běhu programu nezmění,
provádíme kontrolu platformy při každém volání funkce.
Abychom zamezili kontrole, na které platformě program běží, při každém zavolání funkce clear_
screen(), vytvořili jsme funkci clear_screen() s ohledem na používanou platformu jedenkrát při
importu modulu a od tohoto okamžiku ji vždy používáme. To je možné díky tomu, že příkaz def
je příkazem jazyka Python úplně stejně jako kterýkoliv jiný. Jakmile interpret dorazí k příkazu if,
provede buď první, nebo druhý příkaz def, čímž se dynamicky vytvoří první nebo druhá funkce
clear_screen(). Vzhledem k tomu, že tato funkce není definována uvnitř jiné funkce (nebo uvnitř
třídy, jak uvidíme v následující lekci), jedná se o globální funkci, která je přístupná stejně jako
kterákoli jiná funkce v modulu.
Po vytvoření funkce explicitně nastaví její dokumentační řetězec. Díky tomu nemusíme psát stejný
dokumentační řetězec na dvou místech a také vidíme, že dokumentační řetězec je jen jedním z
atributů funkce. Mezi další atributy patří modul funkce a její název.
def resize(max_rows, max_columns, char=None):
“””Změní velikost mřížky, přičemž zahodí obsah a
změní pozadí, nemá-li znak představující pozadí hodnotu None
“””
assert max_rows > 0 and max_columns > 0, “příliš malé”
global _grid, _max_rows, _max_columns, _background_char
if char is not None:
assert len(char) == 1, _CHAR_ASSERT_TEMPLATE.format(char)
_background_char = char
_max_rows = max_rows
_max_columns = max_columns
_grid = [[_background_char for column in range(_max_columns)]
for row in range(_max_rows)]
Tato funkce používá příkaz assert pro vynucení zásady, že pokus o změnu velikosti mřížky na
velikost menší než 1 x 1 představuje chybu programování. Je-li zadán znak pro pozadí, použije se příkaz
assert pro zajištění, že se jedná o řetězec s přesně jedním znakem. Není-li tomu tak, bude
chybovou zprávou tvrzení text konstanty _CHAR_ASSERT_TEMPLATE se zástupným symbolem {0}
nahrazeným zadaným řetězcem char.
Naneštěstí musíme použít příkaz global, protože potřebujeme aktualizovat několik globálních
proměnných uvnitř této funkce. Jak uvidíme v lekci 6, v tomto ohledu nám výrazně pomůže objektově
orientovaný přístup.
Proměnnou _grid vytváříme pomocí seznamové komprehenze uvnitř seznamové komprehenze.
Použití replikace seznamu ([[char] * columns] *) by zde nefungovalo, protože vnitřní seznam
bude sdílený (mělce zkopírovaný). Mohli bychom ale použít vnořené cykly for ... in:
Seznamové kom-
prehenze
¾ 120
Moduly a balíčky





208
Lekce 5: Moduly
_grid = []
for row in range(_max_rows):
_grid.append([])
for column in range(_max_columns):
_grid[-1].append(_background_char)
Tento kód je pravděpodobně méně srozumitelný než seznamová komprehenze a je také mnohem
delší.
Nyní se podíváme jen na jednu z kreslicích funkcí, abychom získali ponětí o tom, jak se takové kreslení
provádí, protože naším hlavním zájmem je implementace modulu. Zde je funkce add_horizontal_
line() rozdělená na dvě části:
def add_horizontal_line(row, column0, column1, char=“-“):
“””Přidá do mřížky vodorovnou čáru s použití zadaného znaku
>>> add_horizontal_line(8, 20, 25, “=”)
>>> char_at(8, 20) == char_at(8, 24) == “=”
True
>>> add_horizontal_line(31, 11, 12)
Traceback (most recent call last):
...
RowRangeError
“””
Dokumentační řetězec obsahuje dva testy, z nichž první by měl fungovat a druhý by měl vyvolat
výjimku. Když v dokumentačních testech pracujeme s výjimkami, stačí uvést řádek „Traceback“, protože
ten je vždy stejný a říká modulu doctest, že očekáváme výjimku, pak následuje výpustek
znamenající další řádky (které se mění) a nakonec řádek s výjimkou, kterou čekáme, že obdržíme. Funkce
char_at() patří mezi funkce tohoto modulu. Vrací znak na zadaném řádku a sloupci v mřížce.
assert len(char) == 1, _CHAR_ASSERT_TEMPLATE.format(char)
try:
for column in range(column0, column1):
_grid[row][column] = char
except IndexError:
if not 0 <= row <= _max_rows:
raise RowRangeError()
raise ColumnRangeError()
Kód začíná stejnou kontrolou délky argumentu char jako ve funkci resize(). Místo explicitní
kontroly argumentů row a column funguje funkce na základě předpokladu, že argumenty jsou platné.
Pokud dojde k výjimce IndexError kvůli přístupu k neexistujícímu řádku nebo sloupci, výjimku
zachytíme a vyvoláme místo ní příslušnou výjimku specifickou pro tento modul. Tento způsob
programování se neformálně označuje jako „je snazší žádat o prominutí než o dovolení“ a ve srovnání
se způsobem „dívej se, než skočíš“, kde se kontroly provádějí předem, je pro jazyk Python obecně
považován za vhodnější. Spoléhání na vyvolání výjimky spíše než na předem provedenou kontrolu





209
je efektivnější v případech, kdy je výskyt výjimek vzácný. (Tvrzení se do oblasti „dívej se, než skočíš“
nepočítají, protože v kódu nasazeném do ostrého provozu by k nim nikdy nemělo dojít – proto jsou
také často deaktivovány komentářem.)
Téměř na konci modulu je za definicemi všech funkcí jediné volání funkce resize():
resize(_max_rows, _max_columns)
Toto volání inicializuje mřížku na výchozí velikost (25 x 80) a zajistí, aby kód, který importuje modul,
mohl tento modul bezpečně a okamžitě používat. Bez tohoto volání by importující program či modul
musel při každém importu tohoto modulu zavolat funkci resize() pro inicializaci mřížky, což by si
programátoři museli pamatovat a mohlo by to navíc vést k vícenásobným inicializacím.
if __name__ == „__main__“:
import doctest
doctest.testmod()
Poslední tři řádky modulu jsou standardní pro moduly, které používají modul doctest pro kontrolu
svých dokumentačních testů. (Testování se budeme podrobně věnovat v lekci 9.)
Modul CharGrid má jeden podstatný nedostatek: podporuje pouze jediný mřížkový znak. To se dá
vyřešit například uchováváním kolekce mřížek v modulu, což by ale znamenalo, že uživatelé modulu
budou muset při volání každé funkce uvádět klíč nebo index označující, na kterou mřížku odkazují.
V případech, kdy je vyžadováno více instancí nějakého objektu, je lepším řešením vytvořit modul,
který definuje třídu (vlastní datový typ), protože můžeme vytvářet tolik instancí třídy (objektů
daného datového typu), kolik jen chceme. Další výhoda vytvoření třídy spočívá v tom, že bychom
nemuseli pro ukládání (statických) dat třídy používat příkaz global. Způsob vytváření tříd si ukážeme
v další lekci.
Přehled standardní knihovny Pythonu
Standardní knihovna Pythonu je obecně popisována jako „včetně baterií“. K dispozici je skutečně
pestrá paleta funkčních prvků rozprostřených do přibližně dvou stovek balíčků a modulů.
Ve skutečnosti bylo pro jazyk Python v průběhu let vyvinuto tolik vysoce kvalitních modulů, že
pokud bychom je všechny začlenili do standardní knihovny, vzrostla by velikost distribučních
balíčků Pythonu přinejmenším o jeden řád. Moduly umístěné do této knihovny jsou tedy spíše odrazem
historického vývoje Pythonu a zájmů jeho hlavních vývojářů než jakkoli koordinovanou či
systematickou snahou o vytvoření „vyvážené“ knihovny. Kromě toho se některé moduly ukázaly jako velmi
obtížně udržovatelné v rámci knihovny – zvláště modul Berkeley DB – a proto byly z knihovny
odebrány a nyní jsou udržovány nezávisle na ní. To znamená, že pro Python je k dispozici řada
skvělých modulů třetích stran, které (bez ohledu na svoji kvalitu a užitečnost) nejsou součástí
standardní knihovny. (Na dva takovéto moduly se později podíváme: moduly PyParsing a PLY použijeme
v lekci 14 pro vytvoření analyzátorů.)
V této části se podíváme na obsáhlejší přehled toho, co vše máme dispozici. Výklad rozdělíme dle
tematických okruhů a vynecháme ty balíčky a moduly, které jsou silně specializované, a také ty, které
jsou určeny pro konkrétní platformu. V mnoha případech si ukážeme malý příklad, abychom si mohli
Přehled standardní knihovny Pythonu





210
Lekce 5: Moduly
některé balíčky a moduly přímo „osahat“. U balíčků a modulů probíraných v jiných částech knihy
jsou k dispozici křížové odkazy.
Práce s řetězci
Modul string nabízí několik užitečných konstant, mezi něž patří string.ascii_letters a string.
hexdigits. Dále nabízí třídu string.Formatter, z níž můžeme odvodit třídu poskytující
přizpůsobené formátování řetězců.
*
Modul textwrap lze použít k zalomení řádků textu na zadanou šířku
a k minimalizaci odsazení.
Modul struct poskytuje funkce pro zabalení, resp. rozbalení, čísel, logických hodnot a řetězců do
(resp. z) objektů typu bytes s použitím jejich binární reprezentace. To může být užitečné při práci
s daty, která se mají odeslat nebo přijmout z nízkoúrovňových knihoven napsaných v jazyku C.
Moduly struct a textwrap používá program convert-incidents.py, na který se podíváme v lekci 7.
Modul difflib nabízí třídy a metody pro porovnávání posloupností, jako jsou kupříkladu řetězce.
Tento modul je schopen vytvořit výstup ve standardních formátech „diff “ i v jazyku HTML.
Nejvýkonnějším modulem Pythonu pro práci s řetězci je modul re (regulární výrazy), který si
podrobně prostudujeme v lekci 13.
Třída io.StringIO nabízí objekty podobné řetězcům, které se chovají jako textový soubor
umístěný v paměti. To může být užitečné, chceme-li pro zápis do řetězce použít stejný kód, který zapisuje
do souboru.
Příklad: Třída io.StringIO
Python nabízí dva odlišné způsoby zápisu textu do souborů. První spočívá v použití metody write()
objektu souboru a druhý v použití funkce print() s klíčovým argumentem file nastaveným na
objekt souboru, který je otevřený pro zápis:
print(„Chybová zpráva“, file=sys.stdout)
sys.stdout.write(“Chybová zpráva ”)
Oba řádky textu se vypíšou do objektu sys.stdout, což je objekt souboru, který představuje
„standardní výstupní proud“. Tento proud je obvykle směrován do konzoly a od objektu sys.stderr
(„chybový výstupní proud“) se liší pouze v tom, že je ukládán do mezipaměti. (Python
automaticky vytváří a otevírá proudy sys.stdin, sys.stdout a sys.stderr při spuštění programu.) Funkce
print() přidává standardně nový řádek, což můžeme potlačit zadáním klíčového argumentu end,
který nastavíme na prázdný řetězec.
V některých situacích je užitečné mít možnost zachytit do řetězce výstup, který má jít do nějakého
souboru. To lze realizovat pomocí třídy io.StringIO, jež poskytuje objekt, který je možné
používat stejně jako objekt souboru, přičemž se všechna zapsaná data uchovají v řetězci. Objektu typu
io.StringIO můžeme předat počáteční řetězec, takže z něj lze také číst jako ze souboru.
* Výraz odvození třídy (nebo též specializace) se používá tehdy, když vytváříme vlastní datový typ (tj. třídu)
založený na jiné třídě. Tomuto tématu se budeme plně věnovat v lekci 6.
typ bytes
¾ 286
modul
struct
¾ 288





211
Ke třídě io.StringIO můžeme přistupovat po importu modulu io a můžeme ji použít k zachycení
výstupu určeného pro objekt souboru, jako je například sys.stdout:
sys.stdout = io.StringIO()
Pokud tento řádek umístíme na začátek programu za příkazy import, ale před jakékoliv použití
proudu sys.stdout, odešle se veškerý text posílaný do proudu sys.stdout do objektu io.StringIO, který
jsme vytvořili na tomto řádku a který nahradil standardní objekt souboru sys.stdout. Když se nyní
provedou výše uvedené řádky print() a sys.stdout.write(), nepůjde jejich výstup do konzoly,
ale do objektu io.StringIO. (Původní proud sys.stdout můžeme kdykoliv obnovit příkazem sys.
stdout = sys.__stdout__.)
Všechny řetězce, které byly zapsány do objektu io.StringIO, můžeme získat pomocí funkce
io.StringIO.getvalue(), což v našem případě znamená voláním funkce sys.stdout.getvalue().
Její návratovou hodnotou je řetězec obsahující všechny řádky, které byly dosud zapsány. Tento
řetězec můžeme vypsat nebo uložit do souboru protokolu nebo poslat přes síťové připojení jako
jakýkoliv jiný řetězec. S dalším příkladem použití třídy io.StringIO se setkáme v pozdější části této lekce
(strana 233).
Programování na příkazovém řádku
Pokud potřebujeme, aby náš program byl schopen zpracovat text, který mohl být přesměrován
z konzoly nebo který mohl být v souborech uvedených na příkazovém řádku, pak můžeme použít
funkci fileinput.input() modulu fileinput. Tato funkce prochází všechny řádky přesměrované
z konzoly (jsou-li nějaké) a všechny řádky v souborech uvedených na příkazovém řádku jako
spojitou posloupnost řádků. Modul umí prostřednictvím funkcí fileinput.filename() a fileinput.
lineno() ohlásit aktuální název souboru a číslo řádku a dále dokáže pracovat s některými typy
komprimovaných souborů.
Pro práci s volbami příkazového řádku jsou k dispozici dva samostatné moduly. Modul getopt je
populární, protože jej lze jednoduše používat a je již delší dobu součástí knihovny. Modul optparse
je novější a výkonnější.
Příklad: Modul optparse
V lekci 2 jsme si popsali program csv2html.py. Ve cvičeních druhé lekce jsme navrhli rozšíření
tohoto programu spočívající v přijímání argumentů z příkazového řádku („maxwidth“ jako celé
číslo a „format“ jako řetězec). Modelové řešení (csv2html2_ans.py) má pro zpracování argumentů
funkci o velikosti 26 řádků. Zde je začátek funkce main() programu csv2html2_opt.py, což je další
verze programu, která pro zpracování argumentů příkazového řádku nepoužívá vlastní funkci, ale
modul optparse:
def main():
parser = optparse.OptionParser()
parser.add_option(“-w”, “--maxwidth”, dest=”maxwidth”, type=”int”,
help=(“maximální počet znaků, které lze “
“vypsat do řetězcových polí [výchozí: %default]”))
parser.add_option(“-f”, “--format”, dest=”format”,
příklad
csv2html.
py
¾ 100
Přehled standardní knihovny Pythonu





212
Lekce 5: Moduly
help=(“formát pro výpis čísel “
“[výchozí: %default]”))
parser.set_defaults(maxwidth=100, format=”.0f”)
opts, args = parser.parse_args()
Stačí pouze devět řádků kódu plus příkaz import optparse. Kromě toho nepotřebujeme explicitně
řešit volby -h a --help, o něž se postará modul optparse, který vypíše vhodnou zprávu o použití
programu pomocí textů z klíčových argumentů help, v nichž nahradí text „%default“ výchozí
hodnotou příslušné volby.
Dále si všimněte, že volby nyní používají standardní unixový styl krátkých a dlouhých názvů
začínajících pomlčkou. Krátké názvy jsou vhodné pro interaktivní použití v konzole, zatímco dlouhé názvy jsou
srozumitelnější při použití ve skriptech shellu. Například pro nastavení maximální šířky na 80 můžeme
použít -w80, -w 80, --maxwidth=80 nebo --maxwidth 80. Po analýze příkazového řádku jsou volby
k dispozici prostřednictvím atributů s příslušnými názvy, například opts.maxwidth a opts.format.
Všechny argumenty, které nebyly zpracovány (obvykle názvy souborů), jsou v seznamu args.
Pokud během analýzy příkazového řádku dojde k nějaké chybě, zavolá modul optparse funkci sys.
exit(2). To vede k čistému ukončení programu, při němž operační systém obdrží jako návratovou
hodnotu programu číslo 2. Návratová hodnota 2 standardně označuje chybu při použití, 1 označuje
jakýkoliv jiný druh chyby a 0 znamená úspěch. Pokud funkci sys.exit() zavoláme bez argumentů,
vrátí operačnímu systému hodnotu 0.
Matematika a čísla
Kromě vestavěných čísel typu int, float a complex nabízí knihovna čísla typu decimal.Decimal
a fractions.Fraction. K dispozici máme tři numerické knihovny: math pro standardní
matematické funkce, cmath pro matematické funkce pracující s komplexními čísly a random poskytující řadu
funkcí pro generování náhodných čísel. Tyto moduly jsme si představili v lekci 2.
Numerické abstraktní bázové třídy jazyka Python (tj. třídy, od nichž lze odvozovat další třídy, ale
které nelze použít přímo) se nacházejí v modulu numbers. Tyto třídy jsou užitečné pro kontrolu,
zda daný objekt x představuje libovolný druh čísla (např. isinstance(x, numbers.Number)) nebo
zda je specifickým druhem čísla (např. isinstance(x, numbers.Rational) nebo isinstance(x,
numbers.Integral)).
V oblasti vědeckého a inženýrského programová ní přijde vhod balíček třetí strany s názvem NumPy.
Tento modul nabízí vysoce efektivní n-dimenzionální pole, základní funkce z oblasti lineární
algebry a Fourierových transformací a nástroje pro integraci kódu napsaného v jazyku C, C++ a Fortran.
Balíček SciPy obsahuje modul NumPy, který rozšiřuje o moduly pro statistické výpočty, zpracování
signálu a obrázků, genetické algoritmy a pro řadu dalších oblastí. Oba balíčky jsou k dispozici
zdarma na adrese www.scipy.org.
Datum a čas
Moduly calendar a datetime nabízejí funkce a třídy pro práci s datem a časem. Jsou ovšem založeny
na idealizovaném gregoriánském kalendáři, takže nejsou vhodné pro práci s předgregoriánskými
kalendářními daty. Práce s datem a časem je velice složité téma. Používané kalendáře se v jednotli-





213
vých místech a časech liší, den netrvá přesně 24 hodi n, rok nemá přesně 365 dnů, odlišný je též letní
čas i časová pásma. Třída datetime.datetime (ne však třída datetime.date) si sice dokáže
poradit s časovými pásmy, ale ne sama od sebe. Tento nedostatek napravují moduly třetích stran,
například dateutil z www.labix.org/python-dateutil a mxDateTime z www.egenix.com/products/python/
mx-Base/mxDateTime.
Modul time pracuje s časovými známkami. Jedná se o prostá čísla, která uchovávají počet vteřin od
začátku jisté epochy (1. 1. 1970 00:00:00 na Unixu). Tento modul lze použít pro získání časové
známky aktuálního času na daném stroji v UTC (Coordinated Universal Time – koordinovaný světový
čas) nebo jako místní čas, který bere v potaz letní čas. Dále jej lze použít pro vytváření nejrůznějším
způsobem naformátovaných řetězců s datem, časem a datem i časem. Kromě toho dokáže
analyzovat řetězce obsahující kalendářní data a časy.
Příklad: Moduly calendar, datetime a time
Objekty typu datetime.datetime se obvykle vytvářejí programově, kdežto objekty, jež uchovávají
data a časy v UTC, se obvykle získávají z externích zdrojů, jako jsou časové známky souborů. Zde
je několik příkladů:
import calendar, datetime, time
moon_datetime_a = datetime.datetime(1969, 7, 20, 20, 17, 40)
moon_time = calendar.timegm(moon_datetime_a.utctimetuple())
moon_datetime_b = datetime.datetime.utcfromtimestamp(moon_time)
moon_datetime_a.isoformat() # vrátí: ‘1969-07-20T20:17:40’
moon_datetime_b.isoformat() # vrátí: ‘1969-07-20T20:17:40’
time.strftime(„%Y-%m-%dT%H:%M:%S“, time.gmtime(moon_time))
Proměnná moon_datetime_a je typu datetime.datetime a uchovává datum a čas přistání vesmírné
lodi Apollo 11 na Měsíci. Proměnná moon_time je typu in a uchovává počet vteřin od začátku
epochy po přistání na Měsíci – toto číslo poskytuje funkce calendar.timegm(), která přijímá objekt
typu time_struct získaný od funkce datetime.datetime.utctimetuple() a vrací počet vteřin
reprezentovaných objektem typu time_struct. (K přistání na Měsíci došlo před unixovou
epochou, a proto je výsledné číslo záporné.) Proměnná moon_datetime_b je typu datetime.datetime
a vytváříme ji z celého čísla moon_time, abychom si ukázali převod z počtu vteřin od začátku epochy
na objekt typu datetime.datetime.


       

internetové knihkupectví ABZ - online prodej knih


Knihy.ABZ.cz - knihkupectví online -  © 2004-2018 - ABZ ABZ knihy, a.s. TOPlist