Als je de Python-interpreter afsluit en weer opstart, gaan de definities die je aangemaakt had (functies en variabelen) verloren. Als je een wat groter programma wilt schrijven, kun je dus in plaats daarvan beter een teksteditor gebruiken om de invoer voor de interpreter op te stellen en in een bestand op te slaan, en dit bestand vervolgens aan de interpreter te geven als invoer. Dit noemen we “een script schrijven”. Naarmate je programma langer wordt, wil je het misschien in verschillende bestanden opsplitsen, om het onderhoud te vergemakkelijken. Of je hebt misschien een handige functie geschreven die je in meerdere programma's wilt gebruiken, zonder de functie in ieder afzonderlijk programma te moeten kopiëren.
Ter ondersteuning hiervan is het in Python mogelijk om definities in een apart bestand te zetten, en dit vervolgens te gebruiken in een script of in een interactieve interpretersessie. Zo'n bestand heet een module; definities uit een module kunnen geïmporteerd worden in andere modules of in de main module (de main module is de verzameling variabelen waar je toegang toe hebt in een script dat op top-level wordt uitgevoerd, of in “rekenmachine-modus”).
Een module is een bestand wat Python-definities en -statements
bevat. De bestandsnaam wordt gevormd door de modulenaam met het
achtervoegsel .py. Binnen
de module is de modulenaam (als een string) beschikbaar als de waarde
van de globale variabele __name__.
Maak nu met je favoriete teksteditor een bestand aan in de huidige directory, noem het fibo.py , en zet er het volgende in:
# Module voor Fibonaccigetallen
def fib(n): # druk Fibonaccireeks af tot n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
def fib2(n): # geef Fibonaccireeks tot n terug
resultaat = []
a, b = 0, 1
while b < n:
resultaat.append(b)
a, b = b, a+b
return resultaatStart nu de Python-interpreter op en importeer deze module met het volgende commando:
>>> import fibo
Hiermee worden niet de namen van de functies die in fibo
gedefinieerd zijn, in de huidige symbol table opgenomen; wel wordt de
modulenaam fibo daarin ingevoerd. Met behulp van de
modulenaam kun je de functies nu benaderen:
>>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo'
Als je van plan bent een functie vaak te gebruiken, kun je deze toekennen aan een lokale naam (variabele):
>>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Een module kan zowel uitvoerbare statements als functiedefinities bevatten. De uitvoerbare statements zijn dan bedoeld om de module te initialiseren, en worden alleen de eerste keer dat een module ergens geïmporteerd wordt, uitgevoerd.6.1
Iedere module heeft een eigen symbol table, die door alle in de
module gedefinieerde functies gebruikt wordt als globale symbol
table. Op die manier kan de auteur van een module globale variabelen
gebruiken in de module, zonder bang te hoeven zijn voor botsingen met
de globale variabelen van de gebruiker van de module. Aan de andere
kant is het wel mogelijk (als je weet wat je doet) om aan de globale
variabelen binnen een module te komen, met dezelfde notatie die
gebruikt wordt om aan zijn functies te refereren: modname.itemname.
Modules kunnen weer andere modules importeren. Het is gebruikelijk, maar niet verplicht, om alle import-statements aan het begin van de module (of het script) op te nemen. De geïmporteerde modulename worden in de symbol table van de importerende module gezet.
Met een variant van het import-statement kunnen namen uit een module rechtstreeks in de symbol table van de importerende module opgenomen worden. Bijvoorbeeld:
>>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
De naam van de module waaruit de functies worden geïmporteerd,
wordt nu niet in de symbol table van de importerende module opgenomen
(in het voorbeeld is fibo dus niet gedefinieerd).
Dan is er ook nog een variant waarmee alle namen uit een module geïmporteerd kunnen worden:
>>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Hierdoor worden alle namen geïmporteerd die in de module
gedefinieerd worden, behalve die namen die met een underscore (_)
beginnen.
Wanneer een module met de naam spam wordt geïmporteerd, zoekt de interpreter naar een bestand genaamd spam.py; eerst in de huidige directory, en vervolgens in de lijst met directories die gespecificeerd wordt door de omgevingsvariabele PYTHONPATH. Deze heeft dezelfde syntax als de shell-variabele PATH: een list van directorynamen. Als PYTHONPATH niet gedefinieerd is, of als het bestand niet in het pythonpath gevonden kan worden, wordt de zoektocht voortgezet in een installatie-afhankelijk standaardpad; onder Unix is dit doorgaans .:/usr/local/lib/python.
Preciezer gezegd: er wordt naar modules
gezocht in de directorylijst die gespecificeerd wordt door de
variabele sys.path , die geïnitialiseerd wordt met
de directory waar het invoerscript in staat (of de huidige
directory), PYTHONPATH en de installatie-afhankelijke standaard.
Hierdoor wordt het voor Python-programma's mogelijk om het zoekpad
voor modules aan te passen of te vervangen. Merk op dat, omdat de
directory waar het huidige script in staat, voorkomt in het zoekpad
(en zelfs als eerste doorzocht wordt), het belangrijk is om het
script niet dezelfde naam te geven als een standaardmodule; doe je
dat wel, dan zal Python, wanneer hij een import
<standaardmodule> -statement tegenkomt, proberen om het
script te laden in plaats van de standaardmodule. In de meeste
gevallen is dit niet de bedoeling en levert het een foutmelding op.
Zie paragraaf 6.2,
``Standaardmodules,'' voor meer informatie.
Om de opstarttijd voor kleine programma's die veel standaardmodules gebruiken, aanzienlijk te versnellen, is de volgende maatregel ingevoerd: als in de directory waar spam.py wordt gevonden, een bestand voorkomt met de naam spam.pyc , dan wordt aangenomen dat dit een kant-en-klare “byte-compiled” versie van de module spam is. De wijzigingsdatum en -tijd van de versie van spam.py die gebruikt werd om spam.pyc te compileren, wordt vastgelegd in spam.pyc; de .pyc file wordt genegeerd als deze niet overeenkomen met de wijzigingsdatum en -tijd van het spam.py-bestand in de directory.
Normaal gesproken hoef je niets bijzonders te doen om het spam.pyc-bestand aan te maken. Iedere keer wanneer spam.py met succes gecompileerd is, wordt geprobeerd om de gecompileerde versie weg te schrijven naar spam.pyc. Als deze poging mislukt, wordt geen foutmelding gegenereerd; als om wat voor reden dan ook het bestand niet volledig kan worden weggeschreven, wordt het resulterende spam.pyc-bestand als ongeldig herkend, en dus genegeerd. De inhoud van het spam.pyc-bestand is platformonafhankelijk, dus een directory met Python-modules kan door machines van meerdere architecturen gedeeld worden.
Een paar tips voor gevorderden:
Als de Python-interpreter wordt aangeroepen met de optie -O,
wordt geoptimaliseerde code gegenereerd; deze wordt opgeslagen in
een .pyo-bestand. De
optimizer maakt nu nog niet veel verschil; hij verwijdert alleen
assert statements uit de code. Als -O gebruikt
wordt, wordt alle bytecode geoptimaliseerd; alle bestaande
.pyc-bestanden worden genegeerd, en de .py-bestanden
worden gecompileerd om geoptimaliseerde bytecode te genereren.
Als de interpreter wordt aangeroepen met een dubbele -O
optie (-OO), zal de bytecode-compiler een aantal
optimalisaties uitvoeren die in zeldzame gevallen tot fouten in
programma's kunnen leiden. Op dit moment worden alleen de __doc__
strings verwijderd uit de bytecode, met als resultaat compactere
.pyo-bestanden. Aangezien
sommige programma's afhankelijk zouden kunnen zijn van de
aanwezigheid daarvan, wordt geadviseerd deze opties alleen te
gebruiken als je exact weet wat je doet.
Voor de executiesnelheid van een programma maakt het niet uit of het uit een .pyc-, een .pyo – of een .py-bestand geladen wordt; het enige wat sneller is aan een .pyc- of .pyo-bestand, is het laden zelf.
Wanneer een script uitgevoerd wordt door zijn naam op de command-line mee te geven, wordt de bytecode voor het script nooit naar een .pyc- or .pyo-bestand geschreven. Je kunt dus de opstarttijd van een script terugbrengen door het grootste deel van de code in een module onder te brengen, en een klein scriptje over te houden dat die module importeert. Het is ook mogelijk op de command-line rechtsreeks een .pyc- of .pyo-bestand aanroepen.
Je kunt het bestand spam.pyc (of spam.pyo als -O gebruikt wordt) gebruiken zonder het bestand spam.py voor die module. Op die manier kun je een library met Python-code distribueren in een vorm die wat minder makkelijk te reverse engineeren is.
De module compileall kan .pyc-bestanden(of .pyo-bestanden als -O gebruikt wordt) compileren voor alle modules in een directory.
Python wordt geleverd met een library met
standaardmodules; deze worden beschreven in een apart document, de
Python Library
Reference (hierna te noemen “Library Reference”).
Sommige van deze modules zijn ingebouwd in de interpreter; deze geven
toegang tot operaties die geen onderdeel uitmaken van de kern van de
taal, maar die toch ingebouwd zijn om redenen van efficiëntie,
of om toegang te geven tot kernfuncties van het besturingssysteem,
zoals system calls. Welke modules deze verzameling precies bevat, is
mede afhankelijk van het platform waarop Python gedraaid wordt.
Bijvoorbeeld: de module amoeba wordt alleen ter beschikking
gesteld op systemen die Amoeba op één of andere manier
ondersteunen. Eén module verdient speciale aandacht: sys;
deze is in iedere Python-interpreter ingebouwd. De variabelen sys.ps1
en sys.ps2 definiëren de strings die gebruikt
worden als primaire en secundaire prompts:
>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = 'C> ' C> print 'Bah!' Bah! C>
Deze twee variabelen zijn alleen gedefinieerd als de interpreter in de interactieve modus draait.
De variabele sys.path
is een lijst van strings die het zoekpad voor modules bepaalt. De
variabele wordt geïnitialiseerd op een standaardpad, wat
gekopieerd wordt van de omgevingsvariabele PYTHONPATH, of van een
ingebouwde standaardwaarde in het geval dat PYTHONPATH niet
gedefinieerd is. Je kunt het pad aanpassen met behulp van de
standaard lijstoperaties:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')De ingebouwde functie dir() wordt gebruikt om uit te vinden welke namen gedefinieerd worden door een module. Er wordt een gesorteerde list met strings teruggegeven:
>>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2'] >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'callstats', 'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions']
Wanneer geen argumenten meegegeven worden in de aanroep, geeft dir() een list met de namen die op dat moment gedefinieerd zijn:
>>> a = [1, 2, 3, 4, 5] >>> import fibo, sys >>> fib = fibo.fib >>> dir() ['__name__', 'a', 'fib', 'fibo', 'sys']
Merk op dat alle typen namen meegenomen worden: variabelen, modules, functies, etc.
dir() neemt de namen van ingebouwde functies en variabelen niet mee. Als je daar een lijst van wilt hebben, kun je die vinden in de standaardmodule __builtin__:
>>> import __builtin__ >>> dir(__builtin__) ['ArithmeticError', 'AssertionError', 'AttributeError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'IOError', 'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeError', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__', '__import__', '__name__', 'abs', 'apply', 'bool', 'buffer', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'round', 'setattr', 'slice', 'staticmethod', 'str', 'string', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
Packages maken het mogelijk om structuur in de Python-modulenamespace aan te brengen door het gebruik van “dotted module names” (modulenamen gescheiden door punten). Zo duidt de modulenaam A.B een submodule “B” in het package “A” aan. Hierdoor hoeven auteurs van packages met meerdere modules zich er geen zorgen over te maken of de namen van hun afzonderlijke modules wel uniek zijn: door deze manier van naamgeving worden de namen vanzelf uniek.
Stel je voor dat je een verzameling modules (een package) wilt ontwerpen waarmee audiobestanden in programmatuur op uniforme wijze behandeld kunnen worden. Er zijn veel verschillende bestandsformaten voor audiobestanden (die meestal van elkaar onderscheiden worden aan de hand van hun extensies, bijvoorbeeld: .wav, .aiff, .au), dus je verzameling van modules voor conversie tussen de verschillende bestandsformaten zal waarschijnlijk steeds verder groeien. Ook zijn er veel bewerkingen te bedenken die je met de audiodata kunt uitvoeren (bijvoorbeeld mixen, echo toevoegen, equalizen, een kunstmatig stereo-effect creëren), dus de stroom modules die je kunt schrijven om deze bewerkingen uit te voeren, is eindeloos. Je zou je package als volgt kunnen structureren (uitgedrukt in termen van een hiërarchisch bestandssysteem):
Sound/ Top-level package
__init__.py Initialisatie van het audio package
Formats/ Subpackage voor conversies tussen bestandsformaten
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
Effects/ Subpackage voor geluidseffecten
__init__.py
echo.py
surround.py
reverse.py
...
Filters/ Subpackage voor filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
Als Python een package importeert, zoekt hij in de directories in
sys.path naar de subdirectory van het package.
De __init__.py-bestanden
zijn nodig om aan Python duidelijk te maken dat de betreffende
directories als packages behandeld moeten worden; door deze eis te
stellen, wordt voorkomen dat directories met een gangbare naam, zoals
“string”,
per ongeluk modules afschermen die pas verderop in het module-zoekpad
voorkomen. In het simpelste geval is __init__.py
gewoon een leeg bestand, maar het kan ook initialisatiecode voor het
package bevatten, of de __all__ variabele definiëren,
zoals verderop wordt beschreven.
De gebruikers van het package kunnen afzonderlijke modules uit het package importeren, bijvoorbeeld:
import Sound.Effects.echo
Hierdoor wordt de submodule Sound.Effects.echo geladen. Deze moet via zijn volledige naam gerefereerd worden.
Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)
Een alternatief is:
from Sound.Effects import echo
Niet alleen wordt hiermee de submodule echo geladen, deze wordt ook beschikbaar gemaakt zonder package-voorvoegsel; de module kan dus als volgt gebruikt worden:
echo.echofilter(input, output, delay=0.7, atten=4)
Nog een mogelijkheid is het rechtstreeks importeren van de gewenste functie of variabele:
from Sound.Effects.echo import echofilter
Ook hier wordt de submodule echo rechtstreeks geladen, alleen is deze keer de functie echofilter() rechtstreeks beschikbaar:
echofilter(input, output, delay=0.7, atten=4)
Merk op dat, wanneer from package import item
gebruikt wordt, het item zowel een submodule (of subpackage) van het
package kan zijn, als een andere naam die in het package gedefinieerd
wordt, zoals een functie, een class of een variabele. Het
import-statement test eerst of het item in het package
gedefinieerd is; zo niet, dan neemt Python aan dat het een module is,
en probeert deze te laden. Als dat niet lukt, wordt een ImportError
exceptie gegenereerd.
Dit in tegenstelling tot het gebruik van de import
item.subitem.subsubitem syntax: hierbij
moet ieder item, behalve het laatste, een package zijn;
het laatste mag een module of package zijn, maar geen class, functie
of variabele die gedefinieerd wordt in het vorige item.
Wat gebeurt er als de gebruiker from Sound.Effects import *
intypt? In het
ideale geval gaat Python terug naar het bestandssysteem, zoekt hij
uit welke submodules deel uitmaken van het package, en importeert hij
deze allemaal. Helaas werkt dit op Mac- en Windows-platforms niet
vlekkeloos, aangezien het bestandssysteem op die platformen niet
altijd de juiste informatie heeft over de juiste case (hoofd-
of kleine letters) van een bestandsnaam! Het is dus niet mogelijk om
voor deze platformen af te leiden of het bestand ECHO.PY
geïmporteerd moet worden als module echo, Echo
of ECHO. (Windows 95 heeft bijvoorbeeld de irritante
gewoonte om van de eerste letter van alle bestandsnamen een
hoofdletter te maken.) Ook de DOS 8+3-beperking ten aanzien van
bestandsnamen brengt een interessant probleem met zich mee voor lange
modulenamen.
De enige oplossing is om de auteur van het package zelf een
expliciete index van de inhoud van het package te laten maken. Het
import-statement gebruikt de volgende conventie: als in de
__init__.py van het
package een lijst met de naam __all__ gedefinieerd is,
wordt deze beschouwd als de lijst van modules die geïmporteerd
moet worden bij gebruik van from package import *.
Het is aan de auteur van het package om deze lijst bij te werken bij
het uitbrengen van nieuwe packageversies. Packageschrijvers kunnen er
ook voor kiezen om deze vorm van het import-statement niet te
ondersteunen, als ze het importeren van * vanuit hun package onnodig
of onwenselijk vinden. Het bestand Sounds/Effects/__init__.py
zou bijvoorbeeld de volgende code kunnen bevatten:
__all__ = ["echo", "surround", "reverse"]
In dit geval heeft from Sound.Effects import * tot
gevolg dat de drie genoemde submodules van het Sound package
geïmporteerd worden.
Als __all__ niet gedefinieerd is, heeft from
Sound.Effects import * dus niet tot gevolg dat alle
submodules van het package Sound.Effects in de huidige
current namespace geïmporteerd worden; het zorgt er alleen voor
dat het package Sound.Effects wordt geïmporteerd
(waarbij zijn initialisatiecode wordt uitgevoerd, indien aanwezig in
__init__.py) en importeert
daarna de namen die aanwezig zijn in het package; inclusief namen die
gedefinieerd worden (en submodules die expliciet geladen worden) door
__init__.py. Daar zitten
ook submodules van het package bij die expliciet geladen zijn door
eerdere import-statements. Zie de volgende code:
import Sound.Effects.echo import Sound.Effects.surround from Sound.Effects import *
In dit voorbeeld worden de echo en surround modules geïmporteerd
in de huidige namespace omdat ze gedefinieerd worden in het
Sound.Effects package tijdens de uitvoering van het
from...import-statement. (Dit werkt ook als __all__
gedefinieerd is.)
Merk op dat de praktijk van het importeren van * uit
een module of package in het algemeen wordt afgeraden, aangezien het
meestal leidt tot slecht leesbare code. Het kan echter geen kwaad om
het tijdens interactieve sessies te gebruiken om typwerk te besparen;
daarnaast zijn sommige modules zo ontworpen dat ze alleen die namen
exporteren die aan bepaalde patronen voldoen.
Er is overigens niets mis met de vorm from Package import
specific_submodule! Sterker nog, dit is de aanbevolen
notatiewijze, tenzij de importerende module meerdere submodules met
dezelfde naam in verschillende packages moet kunnen gebruiken.
Submodules moeten vaak aan elkaar refereren. De surround
module zou bijvoorbeeld gebruik kunnen maken van de echo
module. Dit soort referenties is zelfs zo gebruikelijk dat het
import-statement eerst binnen het package zelf kijkt,
voordat hij overgaat op het module-zoekpad. De surround-module kan
dus simpelweg import echo of from echo import
echofilter gebruiken. Als de te importeren module niet
gevonden kan worden in het huidige package (het package waar de
huidige module een submodule van is), dan zoekt het import-statement
naar een top-level module met de opgegeven naam.
Wanneer de packages onderverdeeld zijn in subpackages (zoals het
geval is met het Sound package in het voorbeeld), is er geen
verkorte notatie beschikbaar om te refereren aan submodules van
andere subpackages – je moet dan de volledige naam van het
subpackage gebruiken. Als de module Sound.Filters.vocoder
bijvoorbeeld de echo module in het Sound.Effects
package wil gebruiken, kan hij deze importeren door middel van from
Sound.Effects import echo.
Packages ondersteunen nog een ander speciaal attribuut, __path__. Dit attribuut wordt geïnitialiseerd als een lijst met de naam van de directory waar het __init__.py-bestand van het package staat; deze initialisatie vindt plaats voordat de code in __init__.py wordt uitgevoerd. Deze variabele kan door de gebruiker worden gewijzigd; daarmee wordt het zoeken naar modules en subpackages binnen het package beïnvloed.
Hoewel je deze mogelijkheid niet vaak nodig zult hebben, kan hij van pas komen bij het uitbreiden van de verzameling modules die onderdeel uitmaakt van een package.
|
Python Tutorial |
|