5
Moduly

### Proč používat moduly?

### Základy

def tiskarna(x):  # je atributem modulu – je na nejvyší úrovni
    print x

% python
>>> import modul1                      # načti modul
>>> modul1.tiskarna('Hello world!')    # musíme blíže určit
Hello world!

>>> from modul1 import tiskarna        # načti atribut do ...
>>> tiskarna('Hello world!')           # globalního jm. prostoru
Hello world!

>>> from modul1 import *               # načti všechny atributy
>>> tiskarna('Hello world!')
Hello world!

### Moduly jsou jmenné prostory

print 'načítáme ...',

import sys
jmeno = 42

def funkce(): pass
class klass: pass

print 'konec načítání.'

>>> import modul2
načítáme ... konec načítání.

>>> modul2.sys
<module 'sys'>
>>> modul2.jmeno
42
>>> modul2.funkce, module2.klass
(<function funkce at 765f20>, <class klass at 76df60>)

>>> modul2.__dict__.keys()
['__file__', 'jmeno', '__name__', 'sys', '__doc__', '__builtins__', 'klass', 'func']

### import

% cat jednoduchy.py
print 'hello'               # cat jmenosouboru je myšleno: 
neco = 1                    #  vytvořte tento soubor

% python
>>> import jednoduchy       # první import, kód spuštěn
hello
>>> jednoduchy.neco
1
>>> jednoduchy.neco = 2     # změníme atribut 
>>> import jednoduchy       # kód se ale znovu nespustí ...
>>> jednoduchy.neco         # a nic se tedy nezmění
2

% cat maly.py
x = 1
y = [1, 2]

% python
>>> from maly import x, y        # načte celé, kopíruje dvě jm.
>>> x = 42                       # lokální
>>> y[0] = 42                    # přes sdílenou referenci

>>> import maly                  # znovu nenačte!
>>> maly.x                       # maly.x není lokální x
1
>>> maly.y                       # přes sdílenou referenci
[42, 2]

import modul                     # získáme objekt
jmeno1 = modul.jmeno1            # přes přiřazení kopírujeme
jmeno1 = modul.jmeno2            #  daná jména
...
del modul                        # jméno modul nezůstane

### Opětovné načítání modulů

import modul
používáme atributy modulu
...                                          # změníme soubor
reload(modul)                                # načteme znovu
používáme atributy čerstvě načteného modulu

% cat menavka.py
verze = "číslo jedna"
def oznamovatel():
    print verze

% python
>>> import menavka
>>> menavka.oznamovatel()
číslo jedna
>>>

% cat menavka.py
verze = "číslo pět"
def oznamovatel():
    print 'Po dalším načtení:', verze

>>> import menavka
>>> menavka.oznamovatel()                            # nenačte
číslo jedna

>>> reload(menavka)                                  # načte
<module 'menavka' from 'C:\Python\menavka.pyc'>
>>> menavka.oznamovatel()                            # nová ver.
Po dalším načtení: číslo pět

### Věcičky

def testuj():
    print "To 'sou supr baráky ..."

if __name__ == '__main__':     # pokud je modul náš spuštěn
    testuj()                   #  -- ne importován

% python
>>> import spustme
>>> spustme.testuj()
To 'sou supr baráky ...

% python spustme.py
To 'sou supr baráky ...

>>> import sys
>>> sys.path
['.', 'C:\\Python\\lib', 'C:\\Python\\lib\\tkinter']

>>> sys.path = ['.']                      # seznam změníme ...
>>> sys.path.append('C:\\Python')         #  místo 'C:\' 'C:\\'
>>> sys.path                              #  nebo r'C:\' 
['.', 'C:\\Python']

>>> import string
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
ImportError: No module named string

M.jmeno                        # bližší určení
M.__dict__['jmeno']            # slovník jmenného prostoru
sys.modules['M'].jmeno         # sl. aktuálně načtených modulů
getattr(M, 'jmeno')            # std. fce., vrací atribut modulu

# První pokusy s introspekcí (funkce prochazej)

ukecane = 1

def prochazej(modul):
    "Fce vypisující obs. jm. prostoru (přes __dict__)"
    if ukecane:
        print "-"*32
        print "Modul %s (%s)" % (modul.__name__, modul.__file__)
        print "-"*32
    pocet = 0
    for atrib in modul.__dict__.keys():    # procházíme jm. pr.
        print "%02d) %s \t" % (pocet, atrib),
        if atrib[0:2] == "__": print "<standardní jméno>"
        else: print getattr(modul, atrib)  # a la __file__
        pocet += 1
    if ukecane:
        print "-"*32
        print "Celkem jmen v %s: %d" % (modul.__name__, pocet)

if __name__ == "__main__":
    import meta1                           # s reloadem i zmeny
    prochazej(meta1)                       # prochazim sama sebe

C:\Python> python meta1.py

--------------------------------
Modul meta1 (C:\Python\meta1.py)
--------------------------------
00) prochazej 	<function prochazej at 0x011A595C>
01) __builtins__ 	<standardní jméno>
02) __name__ 	<standardní jméno>
03) __file__ 	<standardní jméno>
04) __doc__ 	<standardní jméno>
05) ukecane 	1
--------------------------------
Celkem jmen v meta1: 6

### Oblíbené problémy

>>> import "string"
Traceback (  File "<interactive input>", line 1
    import "string"
                  ^
SyntaxError: invalid syntax

>>> jmeno = "string"
>>> exec "import " + jmeno           # spustí předaný řetězec
>>> string                           # import v akt. jm. prost.
<module 'string'>

>>> jmeno = "string"
>>> string = __import__(jmeno)
>>> string
<module 'string'>

X = 99
def tiskX(): tisk X

% cat vnorene2.py
from nested1 import X, tiskX         # kopíruje jména
X = 88                               # mění pouze lokální
tiskX()                              # v modulu stále 99

% python vnorene2.py
99

% cat vnorene3.py
import vnorene1
vnorene1.X = 88                      # přistupujeme přímo
vnorene1.tiskX()

% python vnorene3.py
88

fce1()               # chyba: "fce1" ještě nepřiřazeno

def fce1():
    print fce2()     # ok: "fce2" se bude hledat až později

fce1()               # chyba: "fce2" ještě nepřiřazeno 

def fce2():
    return "Hello"

fce1()               # ok: "fce1" i "fce2" přiřazeno

% cat recur1.py
x = 1; import recur2; y = 2 

% cat recur2.py
from recur1 import x;  # ok: jménu X už bylo přiřazeno
from recur1 import y;  # chyba: ... Y zatím ne

>>> import recur1
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
  File "recur1.py", line 2, in ?
    import recur2
  File "recur2.py", line 2, in ?
    from recur1 import y
ImportError: cannot import name y

from module import X    # X se stává lokální proměnnou
import module           # pro reload potřebujeme objekt
něco dál
reload(module)          # ovlivní jen objekt typu modul
X                       # nezměněná lokální proměnná

import module           # jen objekt typu modul
něco dál
reload(module)          # ovlivní jen objekt typu modul
module.X                # nově načtená “verze”

% cat A.py
import B                # nebude načteno znovu
import C                # import –- ne reload

% python
něco děláme ... importujeme A
>>> reload(A)

### Shrunutí

### Cvičení