Previous Page

Up One Level

Next Page

Python Tutorial

Contents

Index

Vorige: 5. Datastructuren Omhoog: Python Tutorial Volgende: 7. In- en uitvoer
Onderdelen
  • 6.1 Meer over modules
    • 6.1.1 Het module-zoekpad
    • 6.1.2 “Gecompileerde” Python-bestanden
  • 6.2 Standaardmodules
  • 6.3 De functie dir()
  • 6.4 Packages
    • 6.4.1 * importeren uit een package
    • 6.4.2 Referenties binnen een package
    • 6.4.3 Packages in meerdere directories


6. Modules

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 resultaat

Start 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


6.1 Meer over modules

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.


6.1.1 Het module-zoekpad

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.

6.1.2 “Gecompileerde” Python-bestanden

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.


6.2 Standaardmodules

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')


6.3 De functie dir()

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']


6.4 Packages

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.


6.4.1 * importeren uit een package

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.

6.4.2 Referenties binnen een package

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.

6.4.3 Packages in meerdere directories

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.


Voetnoten

... uitgevoerd.6.1
In feite zijn functiedefinities ook “statements” die worden “uitgevoerd”; door de uitvoering ervan wordt de functienaam opgenomen in de globale symbol table van de module.

Previous Page

Up One Level

Next Page

Python Tutorial

Contents

Index

Vorige: 5. Datastructuren Omhoog: Python Tutorial Volgende: 7. In- en uitvoer
Release 2.3.4, documentation updated on May 20, 2004.
See About this document... for information on suggesting changes.