Moduly a balíčky v Jythonu

V dnešním díle si vysvětlíme, co to jsou moduly a balíčky. Jakým způsobem je možné efektivně organizovat vaše nástroje vytvořené v Jythonu do logických celků.

Moduly

Modul je soubor, který obsahuje kód napsaný v Jythonu, a který má koncovku .py. Jméno souboru žádným způsobem nesouvisí s jeho obsahem jako je tomu v Javě, ale slouží jen k organizaci programů do logických celků.

Moduly můžeme rozdělit do dvou skupin. Do první skupiny patří moduly, které jsou součástí standardní distribuce Jythonu, a můžete je nalézt ve složce Lib vaší instalace. Do druhé skupiny patří uživatelem definované moduly.

Programy, které napíšete v Jythonu, můžete uložit do několika modulů, a tyto pak můžete dále sdružovat do balíčků. Moduly jsou základní strukturální jednotkou programů psaných v Jythonu. Většinou obsahují posloupnost příkazů, které definují proměnné, funkce a třídy. Tyto definice jsou vykonávány při natahování modulu do paměti, a to v pořadí, v jakém jsou v modulu uloženy. Natahování modulu do paměti se děje buď při jeho spuštění pomocí interpretu Jythonu, nebo když je modul poprvé importován jiným modulem.

Jak se vlastně Jython dozví, kde se moduly nachází? Jython obsahuje vestavěný modul, který se jmenuje sys. V tomto modulu existuje proměnná s názvem path, obsahující seznam řetězců, které definují cesty ke složkám, v nichž se budou, v případě potřeby, moduly hledat:

>>> import sys
>>> sys.path
        ['', 'D:\\.', 'D:\\Home\\Jython\\Lib', 'D:\\Home\\Jython']

Podívejme se trochu podrobněji na výše uvedený výpis interaktivního sezení s Jythonem. Přestože modul sys je vestavěný modul, to automaticky neznamená, že jej máme okamžitě k dispozici. Abychom měli přístup k jeho obsahu, je nutné ho nejprve importovat příkazem import sys. Je to modul jako každý jiný, jenom není uložený do samostatného souboru ve složce Lib. Obsah proměnné path, zpřístupníme pomocí operátoru tečka:

modul.attribut

Obsah proměnné sys.path by defaultně měl ukazovat do běžného adresáře, do složky, do které je Jython instalován, a do složky Lib, kde jsou uloženy standardní moduly Jythonu. Obsah této proměnné je možné změnit, buď nastavením systémových proměnných Jythonu (viz. Příloha B), nebo dynamicky během vykonávání programu.

Příkaz import

Příkaz import slouží ke zpřístupnění obsahu požadovaného modulu. Během importu modulu dochází k vykonávání kódu, který je v něm uložen. Je podstatný rozdíl mezi tím, jak je vykonáván příkaz import v Jythonu a jak v Javě. Zatímco v Javě příkaz import slouží k tomu, aby byly názvy tříd použitelné bez udávání plného kvalifikovaného jména, v Jythonu příkaz import skutečně vykonává importovaný soubor.

Příkaz import má následující syntaxi:

import kvalifikovaný_nazev_modulu [as alias][,...]
from kvalifikovaný_nazev_modulu import jmeno1 [as alias] [,...]

 

1. import nazev_modulu

Převeďme si to nyní do srozumitelné řeči. V té nejjednodušší formě má příkaz tvar:

import název_modulu

Uvažujme následující kód, který jsme uložili do souboru s názvem ruzne.py :

#:ruzne.py
"""Toto je modul, na kterem si ukazeme ruzne zpusoby importu.
Tento retezec slouzi jako dokumentacni retezec modulu."""

#zde definuji promennou 'autor'
autor = "Stefan Havlicek"


#nasleduje definice funkce
def ahojSvete(arg='Hello world'):
    """Pozdravi svet.

   Uziti:
      ahojSvete(vstup_parametr)
      vstup_parametr .... nepovinny
      defautni hodnota ... 'Hello world'
"""

    #tiskne na standardni vystup
    print arg
    
#:~


Pokud si nyní otevřu interpret Jythonu v interaktivním modu a chci použít funkci nadefinovanou ve výše uvedeném modulu, musím tento modul naimportovat:

Jython 2.1a1 on java1.4.0 (JIT: null)
Type "copyright", "credits" or "license" for more information.

>>>
>>> import ruzne
>>>


Zadáním tohoto příkazu se natáhl do paměti počítače modul ruzne a byl vykonán kód, který je v něm uložen. V našem případě se vytvořila proměnná autor a byl jí přiřazen odkaz na objekt reprezentující řetězec, který je uveden v přiřazovacím příkazu. Pak se vytvořila proměnná ahojSvete a ji byl přiřazen odkaz na objekt reprezentující funkci, definovanou v modulu. Obě proměnné, tj. autor a ahojSvete, jsou nyní přístupné prostřednictvím plného kvalifikovaného jména ve tvaru nazev_modulu.identifikator_promenne . Skutečně pokud bychom se pokusili přistoupit k obsahu proměnné bez použití plného kvalifikovaného jména, bude vyvolána výjimka NameError.

>>> autor
Traceback (innermost last):
  File "<console>", line 1, in ?
NameError: autor
>>>
>>> ruzne.autor
'Stefan Havlicek'
>>>
>>> ruzne.ahojSvete
<function ahojSvete at 1305259>
>>>

Chceme-li použít funkci ahojSvete, použijeme operátor volání funkce:

>>> ruzne.ahojSvete()
Hello world
>>>
>>> ruzne.ahojSvete('Nazdarek, jak se dari')
Nazdarek, jak se dari
>>>

Dokumentační řetězec funkce, který jak víme je uložen v proměnné __doc__, je možné získat zadáním jeho plného jména:

>>> print ruzne.ahojSvete.__doc__
Pozdravi svet.

   Uziti:
      ahojSvete(vstup_parametr)
      vstup_parametr .... nepovinny
      defautni hodnota ... 'Hello world'
>>>

Obsah dokumentačního řetězce modulu, popisující k čemu je modul určen, získáme analogicky:

>>>
>>> print ruzne.__doc__
Toto je modul, na kterem si ukazeme ruzne zpusoby importu.
Tento retezec slouzi jako dokumentacni retezec modulu.
>>>

Pokud bychom z našeho modulu chtěli importovat jen jeho určitou část, např. jen funkci ahojSvete, lze použít příkaz import takto:

>>> import ruzne.ahojSvete
>>>

Avšak i v tomto případě se na importovanou funkci musíme odkazovat plným jménem.

Uvádění plných jmen funkcí a proměnných může někdy výsledný kód značně znepřehlednit, proto je možné používat aliasy. Aliasy je možné nadefinovat ihned při importu modulu zápisem:

>>> import ruzne.ahojSvete as ahoj

nebo kdykoliv později, přiřazením odkazu uloženého v plném jméně do jména jiného:

>>> ahoj = ruzne.ahojSvete
>>>
>>> ahoj()
Hello world
>>>

 

2. from jmeno_modulu import jmeno

Druhá forma příkazu import má tvar:

from jmeno_modulu import jmeno1[, jmeno2, ...]

Nebo v modifikované verzi

from jmeno_modulu import *


Při importu prováděném tímto způsobem je kód uložený v modulu vykonáván stejně jako v předchozí formě příkazu import, jen s tím rozdílem, že proměnné vytvořené během importu se stávají součástí modulu, který import provádí. To znamená, že nyní jsou objekty definované v importovaném modulu přístupné přímo bez uvádění názvu modulu:

Jython 2.1a1 on java1.4.0 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>>
>>> from ruzne import ahojSvete
>>>
>>> ahojSvete
<function ahojSvete at 8678661>
>>>
>>> ahojSvete()
Hello world
>>>


Obsah celého modulu naimportujeme příkazem:

from jmeno_modulu import *