Moduly

Co jsou to moduly

Pokud budete psát nějaký větší program, jistě nebudete chtít „naplácat“ všechny funkce a třídy do jednoho velkého souboru. Moduly jsou obdobou knihoven v jazyce C (include) nebo Pascal (USES). Jsou to textové soubory s příponou .py (nebo zkompilované soubory s příponou .pyc). Mohou obsahovat funkce, třídy, objekty atd. Existuje mnoho standardních modulů, další si můžete vytvořit.

Volání funkcí a modulů

Moduly se do programu načtou příkazem import jmeno_modulu. Jméno modulu se za příkazem import uvádí bez přípony.

V příkladu se načítá standardní modul sys a používá jeho funkce exit(). Tato funkce ukončí program kdekoliv ji zavoláte.

>>> import sys
>>> sys.exit()
petr: $

Po zavolání příkazu sys.exit() se program ukončí. V případě, že pracujete v interaktivním módu, ukončí se interpret Python a vrátíte se do příkazové řádky.

Importovaný modul můžete přejmenovat pomocí slovíčka as:

>>> import sys as s
>>> s.exit()
petr: $

Chcete-li načíst více modulů najednou, napište je všechny za příkazem import oddělené čárkou.

Nechcete-li volat funkce složitě přes jmeno_modulu.jmeno_fce, můžete načíst funkci přímo:

from jmeno_modulu import jmeno_funkce
>>> from sys import exit
>>> exit()
petr: $

Chcete-li takto načíst více funkcí z modulu, napište je za import a oddělte je čárkou. Chcete-li takto načíst všechny funkce z modulu, napište místo jmena_funkce hvězdičku.

Použití hvězdičky na vestavěné moduly se silně nedoporučuje, protože při importování několika modulů tímto způsobem by se mohly přepsat globální proměnné z vašeho jmenného prostoru, které by měly stejné jméno jako v modulech. Nebo by si mohly moduly navzájem přepsat jména funkcí, tříd atp. Konec konců, moduly jsou tu právě proto, abyste mohli používat jména bez obav, že je použil už někdo jiný. Vyčleněním jmen do modulů se stávají jména unikátní.

Na dalším příkladě ukáži práci s proměnnou ps1 a ps2 z modulu sys. Tyto proměnné určují vzhled promptu v interaktivním režimu. Spusťte Python v interaktivním režimu:

petr: $ python
Python 2.1.3 (#1, Apr 20 2002, 10:14:34)
[GCC 2.95.4 20011002 (Debian prerelease)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> from sys import ps1, ps2, exit # from sys import *
>>> ps1
'>>> '
>>> ps2
'... '
>>> ps1=":-) "
>>> import sys
>>> sys.ps1=":-) "
:-) exit()
petr: $
Tento příklad nefunguje v IDLE, jen v interaktivním režimu Pythonu.

Funkce exit() pracovala tak jak má. Proč ale přiřazení ps1=":-) " nefungovalo a přiřazení sys.ps1=":-) " ano? Odpověď je jednoduchá. Python se při vypisování promptu obrací na standardní modul sys. Příkazem from sys import ps1, ps2 se zkopírovaly proměnné ps1 a ps2 do našeho jmenného prostoru a změna „našich proměnných“ neměla na modul sys pražádný vliv. Druhé přiřazení již s modulem sys pracuje, a tak se dostavil kýžený výsledek. Život (Python?) je holt pes a na takové věci je třeba dávat pozor.

Vytváření vlastních modulů

Vytvořte textový soubor pokus.py s tímto obsahem:

#!/usr/bin/env python3
#
# modul pokus.py
#
x = 'Hello World'
def pozdrav(pocet):
    try:
        for i in range(pocet):
            print(x)
    except TypeError:
        print('Argumentem funkce pozdrav musi byt cele cislo')
        return
    except:
        print('Neocekavana chyba')
        raise
Přípona .py je pro moduly povinná.

Tím jste vytvořili modul pokus a můžete jej používat:

>>> import sys, pokus
>>> pokus.pozdrav(2)
Hello World
Hello World
>>> pokus.x = 'Ahoj'
>>> pokus.pozdrav(1)
Ahoj
>>> sys.exit()

Porovnejte to s následujícím příkladem. Všiměte si, že každý modul má svůj vlastní jmenný prostor. Ke globálním proměnným v modulu přistupujete přes tečkovou notaci. Pomocí konstrukce from ... import ... je zkopírujete do svého jmenného prostoru, ale funkce stále pracují s proměnnými z jmenného prostoru modulu. To je super, protože se tak nemusíte bát, že vám imporotvané funkce budou dělat bordel ve vašem jmenném prostoru.

>>> from pokus import *  # import * používejte raději jen při testování
>>> print(x)
Hello World
>>> pozdrav(1)
Hello World
>>> x = 'Ahoj'
>>> pozdrav(1)
Hello World
>>> pokus.x = 'Ahoj'
>>> pozdrav(1)
Ahoj

V aktuálním adresáři vznikl soubor pokus.pyc. To je zkompilovaný modul pokus.py. Python jej vytváří a aktualizuje automaticky, aby se tím urychlilo načítání modulů. Při druhém načtení modulu pokus se načte pokus.pyc, což je výrazně rychlejší.
V případě, že soubor pokus.py upravíte ,Python si toho všimne sám od sebe a modul znovu skompiluje.

Příkaz import načte soubor během běhu interpretu jen jednou. Druhé zavolání importu už soubor znovu nečte, takže, pokud soubor změníte, import si toho nevšimne. Nezbývá, než po úpravě modulu interpret ukončit a znovu spustit …

Spouštění modulů jako skriptů

Všechno, co do modulu napíšete, se během importu vykonává. V modulu může být nějaký kód, kterým chcete modul inicializovat, ale většinou v něm budete mít jen definice funkcí a tříd.

Pokud spouštíte nějaký skript Pythonu, nastaví se speciální globální proměnná __name__ na hodnotu "__main__", což se dá s výhodou použít pro rozlišení, zda je soubor spouštěn jako skript, nebo je importován.

Do modulů se takto často umísťují testy, které ověřují jeho funkčnost.

#!/usr/bin/env python3
#
# modul pokus.py
#
x = 'Hello World'
def pozdrav(pocet):
    try:
        for i in range(pocet):
            print(x)
    except TypeError:
        print('Argumentem funkce pozdrav musi byt cele cislo')
        raise

# vykonej nejakou inicializaci
print(x)

# pokud je modul spusten jako skript, vykonej testy
if __name__ == "__main__":
    err = False
    try:
        pozdrav('1')
    except TypeError:
        err = True
    finally:
        if not err:
            print('Error: Byla ocekavana vyjimka TypeError')
        else:
            print('Test prosel OK')
$ python pokus.py
Hello World
Argumentem funkce pozdrav musi byt cele cislo
Test prosel OK

Standardní moduly Pythonu

Python obsahuje mnoho standardních modulů, které byste měli znát. Některé popíši v části Standardní knihovna. Dva moduly, které stojí za zvláštní pozornost, popíši tady.

Modul sys

Modul sys obsahuje užitečné proměnné a metody. Některé jsem už ukazoval (ps1, ps2, exit()). Další důležitou proměnnou je sys.path. To je seznam adresářů, kde se hledají moduly.

>>> import sys
>>> print (sys.path)
['', 'C:\\Program Files\\python3.3\\Lib\\idlelib',
'C:\\Windows\\system32\\python33.zip', 'C:\\Program Files\\python3.3\\DLLs',
 'C:\\Program Files\\python3.3\\lib', 'C:\\Program Files\\python3.3',
 'C:\\Program Files\\python3.3\\lib\\site-packages']

Další zajímavé proměnné jsou sys.stdin (standardní vstup), sys.stdout (standardí výstup) a sys.stderr (standardní chybový výstup). Chyby byste měli vypisovat na standardní chybový výstup. Pomocí funkce print toho docílíte takto:

print ("Neco je spatne", file=sys.stderr) # Python 3.0
print >> sys.stderr, 'spam'               # Python 2.7

V sys.argv najdete argumenty příkazové řádky.

Modul copy

Při povídání o jmenném prostoru byla zmíněna problematika vytváření objektů v Pythonu. Přiřazením a = b nevznikne nový objekt, ale jen se v prostou jmen přiřadí stávajícímu objektu nové jméno. Nový objekt může vzniknout těmito způsoby:

1. vytvořením nového objektu

>>> a = 5; b = a
>>> a is b
True
>>> b = 3
>>> a is b
False
>>> a = [5]; b = a
>>> b += [4]
>>> a is b
True
>>> b = b[:]
>>> a is b
False
>>> seznam1 = [a, b]
>>> seznam2 = seznam1[:]
>>> seznam1 is seznam2
False
>>> seznam1[0] is seznam2[0]
True

Všimněte si, že je potřeba skutečně vytvořit nový objekt (například použitím slice viz. b = b[:]) a nestačí jen změnit hodnotu objektu (viz. b += [4]). Taky si všiměte, že vytvořením kopie seznamu se nevytvoří kopie jeho obsahu, takže seznam2[0] stále ukazuje na ten samý objekt, jako seznam1[0].

2. použitím funkcí modulu copy

Použití slice v předházejícím příkladu je sice efektivní, ale když je potřeba vytvořit kopii např. třídy, pak pomůže jen modul copy.

Obsahuje dvě funkce:

copy(arg) Vytvoří kopii objektu arg, objekty v arg se budou odkazovat na tytéž objekty, jako v původním objektu. Jde o tzv. mělkou kopii.
deepcopy(arg) Vytvoří kopii objektu arg a z objektů v arg budou vytvořeny také kopie (rekurzivně se vytvářejí kopie všech objektů v nalezených objektech …). Jde o tzv. hlubokou (deep) kopii.

Funkce těchto funkcí ukazuje následující příklad.

>>> class trida:
        cislo1 = [1]               # třídní proměnná
        def __init__(self):
                self.cislo2 = [1]  # proměnná objektu

>>> x = trida()
>>> y = x
>>> x is y
True
>>> x.cislo2 is y.cislo2
True
>>> import copy
>>> y = copy.copy(x)
>>> x is y
False
>>> x.cislo2 is y.cislo2
True
>>> y = copy.deepcopy(x)
>>> x is y
False
>>> x.cislo2 is y.cislo2 # atributy objektu jsou zkopírovány
False
>>> x.cislo1 is y.cislo1 # třídní proměnná zůstává stejná
True

Proč je x.cislo1 stejný objekt jako y.cislo1? Protože je součástí objektu, který deklaruje třídu trida, nikoliv objektu x (ani y), které jsou instancemi této třídy.

Třída je v Pythonu také objekt, x.cislo1 je proměnná objektu třídy trida.
Komentář Hlášení chyby
Created: 11.9.2005
Last updated: 31.8.2015
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..