Модули

„ Програмиране с Python“, ФМИ

import stefan, nikolay, tocho, alek, dimitark, dimitarp
18.03.2010 г.

Елементарен проблем

world.py:

""" A module for playing with the world. """
def destroy():
    """Destroys the world."""
    print("The world was destroyed!")

def save(kind):
    """Saves a kind."""
    print("All the", kind, "were saved.")

Искаме да ползваме горните функции в много програми, а не искаме да копираме кода във всяка от тях.

Елементарно решение

women.py:

import world
world.save('women')
world.destroy()	

animals.py:

import world
world.save('animals')
world.destroy()	

Работи без проблеми ако трите файла са в една директория. Чрез модули можем да използваме един и същи код много пъти (code reuse).

Атрибути

>>> world	
<module 'world' from '/home/nb/py/world.py'>
>>> world.destroy
<function destroy at 0x00CA46F0>
>>> dir(world)
['__builtins__', '__doc__', '__file__', '__name__', 'destroy', 'save']
>>> world.__doc__
' A module for playing with the world. '
>>> world.__name__
'world'

Области от имена (namespace)(1)

import world
def save_poohs():
    world.save('Poohs')
insane = True
print(dir())

Области от имена (2)

import pooh
import piglet
def breakfast():
    print("Is it already eleven?")
pooh.breakfast()
piglet.breakfast()
breakfast()

Ако използваме модули няма нужда да се притесняваме, че в няколко програми сме използвали едни и същи имена.

Търсене на атрибути

Модули и обхвати

bottles = 1
def add_bottle():
    global bottles
    bottles += 1
import mod
bottles = 5
mod.add_bottle()
print(bottles, mod.bottles)

Използване на модули — import

С конструкцията import можем да ползваме код от външни файлове.

Ето какво се случва, ако изпълним import mod:

Търсене на файла

import mod

Всички по реда на претърсване: списъка sys.path Търси се в:

  1. текущата директория
  2. променливата на средата PYTHONPATH
  3. системни директории с модули
  4. директории, описани в .pth файлове

Модул vs. Програма

def eat(what):
    print(what, "was eaten.")

if __name__ == '__main__':
    eat('The world as we know it')
$ python3 eater.py
The world as we know it was eaten.
>>> import eater

Пакети от модули

Представете си, че имаме две отделни системи, в които има модул на име game

system1/
	game.py
	<други модули>
system2/
	game.py
	<други модули>

Сега напишете система, която използва модулите game и от двете системи:

import game
game.play()

Тук вече имаме малък проблем.

Пакети от модули (2)

Би било много удобно ако можехме да разделим двата модула game в отделни пакети:

import system1.game
import system2.game
system1.game.play()
system2.game.play()

Това е възможно при няколко условия:

При import на по-сложно име се извършва следното:

from mod import names

Понякога е досадно да извикваме всеки път цялото име на някой обект, като universe.milkyway.earth.europe.bg.beautify()

from universe.milkyway.earth.europe.bg import beautify
beautify()

Или даже:

from universe.milkyway.earth.europe.bg import beautify as b
b()

from mod import *

Хубаво ли ви е така:

from mod import a,b,c,d,e,f,g,h,i,j,k,l

И на мен. Затова Python ни позволява да внесем в нашия модул всички имена от някой друг: from mod import *

Пакети от модули (3)

С пакети от модули можем с един замах да import-нем много модули: forest/pooh.py:

name = 'Pooh'
pot = 'Full of honey'

forest/piglet.py:

name = 'Piglet'
baloon = 'Red'

forest/__init__.py:

from . import pooh
from . import piglet
pot = pooh.pot
baloon = piglet.baloon

user.py:

import forest
print(forest.pooh.name)
print(forest.piglet.name)
print(forest.pot)
print(forest.baloon)

import

sys = '/usr/src/sys'
import os
def list_by_ext(path, ext):
    return [d for d in os.listdir(path) if d.endswith('.'+ext)]

# искаме да отпечатаме sys.path
import sys
print(sys.path)

# сега да видим всички питонски файлове в /usr/src/sys
print(list_by_ext(sys, 'py'))
# опс:
TypeError: Can't convert 'module' object to str implicitly

модули в модули:

mod.py
import sys

>>> import mod
>>> mod.sys

import as

import sys as sysmod
print(sysmod.path)

Почти същото е като:

import sys
sysmod = sys
del sys
sysmod.path

само че ще загубим старата стойност на sys

import forest.pooh.name as pooh_name
import forest.piglet.name as piglet_name

Още разни модулни неща (1)

Съществува модул builtins, който съдържа всички вградени функции и други имена:

import builtins
builtins.dir = abs
print(dir(-3))

Още разни модулни неща (2)

Модулите се импортират само веднъж:

>>> import world
>>> world.save('babas')
All the babas were saved.
>>> world.save = 5
>>> import world
>>> world.save
5

Още разни модулни неща (3)

За презареждане трябва да се ползва reload():

>>> world.save
5
>>> from imp import reload
>>> reload(world)
>>> world.save
<function save at 0x015001F0>

Още въпроси?