{count, plural, one {Cursus} other {Cursussen}}
Als je net begint met Python, schrijf je alles in één bestand. Dat werkt prima voor kleine scripts, maar naarmate je programma’s groter worden, wordt één bestand lastig te lezen, lastig te onderhouden en onmogelijk om te hergebruiken tussen projecten. De oplossing die Python biedt, zijn modules.
In deze tutorial leer je wat modules zijn, hoe je ze importeert, hoe je je eigen modules schrijft en de best practices die beginnersscripts onderscheiden van productieklare code. En voordat je je eigen modules gaat schrijven, raad ik je aan om onze cursus Intro to Python for Data Science te bekijken.
Wat zijn Python-modules?
Een module is simpelweg een Python-bestand. Elk bestand met een .py-extensie met Python-code — functies, klassen, variabelen of uitvoerbare logica — is een module. Wanneer je een bestand opslaat met de naam calculation.py, heb je een module gemaakt met de naam calculation.
De kracht van modules komt doordat je ze kunt importeren in andere programma’s. In plaats van dezelfde functie te kopiëren en plakken in meerdere scripts, definieer je die één keer in een module en importeer je hem later wanneer je hem nodig hebt. Zo werkt ook Python’s eigen standaardbibliotheek: verzamelingen vooraf gebouwde modules zoals math, os en random die je met één regel in elk programma kunt gebruiken.
Specifieker zijn er drie soorten modules die je in Python tegenkomt:
-
Ingebouwde modules: meegeleverd met Python zelf, zoals
mathenos, die ik net noemde. -
Third-party modules: geïnstalleerd via
pip, zoalsnumpyofpandas. -
Je eigen modules: elk
.py-bestand dat je zelf schrijft.
Modules importeren in Python
Om de functionaliteit van een module te gebruiken, moet je die importeren in je huidige programma. Je gebruikt het sleutelwoord import samen met de gewenste modulenaam. Wanneer de interpreter een import-instructie tegenkomt, importeert hij de module in je huidige programma.
Je kunt de functies binnen een module gebruiken via een punt- (.)operator samen met de modulenaam.
Laten we eerst kijken hoe je modules uit de standaardbibliotheek gebruikt. In het onderstaande voorbeeld wordt de module math in het programma geïmporteerd zodat je de functie sqrt() kunt gebruiken.
import math # Import the math module
num = 4
print(math.sqrt(num)) # Call the sqrt() function from the math module
Om efficiëntieredenen wordt elke module per interpretersessie maar één keer geïmporteerd. Als je je modules wijzigt, moet je de interpreter daarom opnieuw starten.
Als je een module die je al hebt geïmporteerd wilt herladen (bijv. na het bewerken), gebruik dan importlib.reload().
Let op dat de oude ingebouwde functie reload() niet meer bestaat in Python 3 — importlib.reload() is de huidige en officiële manier om modules te herladen in Python 3.4+
import importlib
importlib.reload(module_name)
Let op: Het herladen van sys, __main__, builtins en andere kernmodules is niet aan te raden. Veel extensiemodules zijn niet ontworpen om meer dan één keer te initialiseren en kunnen bij herladen onvoorspelbaar falen. Beperk je tijdens ontwikkeling tot het herladen van je eigen modules.
Binnenkort: Python introduceert "lazy imports". Die versnellen de opstarttijd door het laden van modules uit te stellen totdat ze voor het eerst worden gebruikt. Dit is handig omdat, zeker in grote projecten, veel modules bovenaan een bestand worden geïmporteerd maar niet direct nodig zijn.
Je eigen Python-modules schrijven
Nu je hebt geleerd hoe je een module in je programma importeert, is het tijd om er zelf een te schrijven en die in een ander programma te gebruiken. Een module schrijven is net als elk ander Python-bestand schrijven. Laten we beginnen met het schrijven van een functie om twee getallen op te tellen/aftrekken in een bestand calculation.py.
def add(x,y):
return (x+y)
def sub(x,y):
return (x-y)
Als je dit script op de commandoregel probeert uit te voeren, gebeurt er niets omdat je het programma niet hebt opgedragen iets te doen. Maak een ander Python-script in dezelfde map met de naam module_test.py en schrijf daar de volgende code in.
import calculation #Importing calculation module
print(calculation.add(1,2)) #Calling function defined in the calculation module
Als je module_test.py uitvoert, zie je "3" als output. Toen de interpreter de import-instructie tegenkwam, werd de module calculation in je code geïmporteerd en kon je met behulp van de puntoperator de functie add() aanroepen.
Uitvoerbare code beschermen met if __name__ == "main__"
Er is één belangrijke gewoonte bij het schrijven van modules: omwikkel code die je alleen direct wilt uitvoeren (niet bij import) met een if __name__ == "__main__"-guard.
# calculation.py
def add(x, y):
return x + y
def sub(x, y):
return x - y
if __name__ == "__main__":
# This only runs when you execute calculation.py directly
# It will NOT run when another script imports this module
print(add(1, 2))
__name__ op "__main__". Wanneer hij wordt geïmporteerd door een ander script, wordt __name__ ingesteld op de bestandsnaam van de module. Dit betekent dat de print-instructie hierboven niet onverwacht wordt uitgevoerd wanneer iemand calculation in zijn eigen programma importeert.Andere manieren om modules te importeren in Python
Er zijn meer manieren om modules te importeren:
-
from .. import-instructie -
from .. import *-instructie -
de geïmporteerde module hernoemen
Using from module import name
De instructie from..import laat je specifieke functies/variabelen uit een module importeren in plaats van alles te importeren. In het vorige voorbeeld, toen je calculation in module_test.py importeerde, werden zowel de functies add() als sub() geïmporteerd. Maar wat als je in je code alleen de functie add() nodig had? Hier is een voorbeeld dat het gebruik van from..import illustreert.
from calculation import add
print(add(1,2))
In het bovenstaande voorbeeld wordt alleen de functie add() geïmporteerd en gebruikt. Valt het gebruik van add() op? Je kunt die nu direct aanroepen zonder de modulenaam te gebruiken. Je kunt ook meerdere attributen importeren door ze in de importinstructie met een komma te scheiden. Zie het volgende voorbeeld:
from calculation import add,sub
Using from module import *
Je kunt alle attributen van een module importeren met deze instructie. Dit maakt alle attributen van de geïmporteerde module zichtbaar in je code.
Hier is een voorbeeld dat het gebruik van from .. import * illustreert:
from calculation import *
print(add(1,2))
print(sub(3,2))
Let op dat je in de professionele wereld from..import en from..import* beter kunt vermijden. Het vervuilt je namespace met elke naam uit die module, maakt het bij het lezen van de code onmogelijk om te zien waar een functie vandaan komt en kan stilletjes namen overschrijven die je al hebt gedefinieerd. Gebruik in plaats daarvan expliciete imports.
Modules hernoemen in Python
Je kunt de module die je importeert hernoemen, wat handig kan zijn wanneer je een betekenisvollere naam wilt geven aan de module of wanneer de modulenaam te lang is om steeds te gebruiken. Je kunt hiervoor het sleutelwoord as gebruiken. Het volgende voorbeeld laat zien hoe je dit in je programma gebruikt.
import calculation as cal
print(cal.add(1,2))
Je bespaarde jezelf wat typewerk door calculation te hernoemen naar cal.
Let op dat je nu niet langer calculation.add(1,2) kunt gebruiken, omdat calculation niet langer wordt herkend in je programma. Wat er gebeurt: zodra je een module een alias geeft met as, is de originele naam in dat script niet meer beschikbaar.
Zoekpad voor modules in Python
Je wilt je modules misschien in verschillende programma’s of projecten gebruiken en hun fysieke locatie in de mapstructuur kan verschillen. Als je een module wilt gebruiken die in een andere map staat, heb je in Python een paar opties.
Wanneer je een module met de naam calculation importeert, zoekt de interpreter eerst naar een ingebouwde module met die naam. Als die niet wordt gevonden, zoekt hij vervolgens naar een bestand met de naam calculation.py in een lijst met mappen die wordt gegeven door de variabele sys.path. sys.path bevat deze locaties:
-
De map die het invoerscript bevat (of de huidige map)
-
PYTHONPATH(een lijst met mapnamen met dezelfde syntax als de shellvariabelePATH) -
De installatieafhankelijke standaardlocatie
Ga ervan uit dat module_test.py in de map /home/datacamp/ staat en je calculation.py hebt verplaatst naar /home/test/. Je kunt sys.path aanpassen om /home/test/ toe te voegen aan de lijst met paden waarin de Python-interpreter naar de module zoekt. Daarvoor moet je module_test.py als volgt aanpassen:
import sys
sys.path.append('/home/test/')
import calculation
print(calculation.add(1,2))
Byte-gecompileerde bestanden in Python
Het importeren van een module vergroot de uitvoeringstijd van programma’s, dus Python heeft een paar trucs om dit te versnellen. Eén manier is het aanmaken van byte-gecompileerde bestanden met de extensie .pyc.
Intern zet Python de broncode om naar een tussenvorm genaamd bytecode. Die wordt vervolgens vertaald naar de moedertaal van je computer en uitgevoerd. Dit .pyc-bestand is handig wanneer je de module de volgende keer vanuit een ander programma importeert — het gaat dan veel sneller omdat een deel van de verwerking die nodig is voor het importeren van een module al is gedaan. Bovendien zijn deze byte-gecompileerde bestanden platformonafhankelijk.
Let op dat deze .pyc-bestanden meestal worden aangemaakt in dezelfde map als de bijbehorende .py-bestanden. Als Python geen schrijfrechten heeft in die map, worden de .pyc-bestanden niet aangemaakt. Deze bestanden worden doorgaans opgeslagen in de map __pycache__ naast je .py-bestanden, met namen zoals calculation.cpython-312.pyc die de gebruikte Python-versie weergeven. Je kunt deze map gerust negeren of opnemen in .gitignore. Python beheert dit automatisch.
De Python-functie dir()
De functie dir() wordt gebruikt om alle namen te achterhalen die in een module zijn gedefinieerd. Ze geeft een gesorteerde lijst strings terug met de namen die in een module zijn gedefinieerd.
import calculation
print(calculation.add(1,2))
print(dir(calculation))
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add', 'sub']
In de output zie je de namen van de functies die je in de module hebt gedefinieerd, add & sub. Attribuut __name__ bevat de naam van de module. Alle attributen die met een underscore beginnen, zijn standaard Python-attributen die bij een module horen.
Conclusie
Een module maken is nodig voor beter codebeheer en hergebruik. Python levert ingebouwde modules die je kunt importeren met het sleutelwoord import. Python laat je ook je eigen modules maken en gebruiken in je programma’s. Het geeft je byte-gecompileerde bestanden om de kosten van het gebruik van modules te beperken, wat de uitvoering sneller maakt. Je kunt dir() gebruiken om de attributen te zien die in de module van je programma zijn gedefinieerd. Dit kan zowel op vooraf gedefinieerde modules als op door de gebruiker gedefinieerde modules.
Als je meer over Python wilt leren, bekijk dan onze cursus Intermediate Python for Data Science.
Veelgestelde vragen
Kan ik een module binnen een functie importeren?
Ja. Je kunt modules binnen functies importeren, maar het is meestal het beste om bovenaan het bestand te importeren voor duidelijkheid en performance.
Wat gebeurt er als twee modules dezelfde naam hebben?
Python importeert de eerste match die het vindt in het modulezoekpad (sys.path). Wees voorzichtig met naamgeving om conflicten te voorkomen.
Moet ik mijn module handmatig naar .pyc compileren?
Nee. Python maakt automatisch .pyc-bestanden aan wanneer je een module importeert—als er schrijfrechten zijn.
Hoe kan ik controleren vanwaar een module wordt geïmporteerd?
Gebruik het __file__-attribuut van de module:
import math
print(math.__file__)
Is het oké om from module import * te gebruiken?
Het werkt, maar wordt niet aangeraden in productiecode. Het kan de namespace vervuilen en het lastiger maken om te volgen wat er gebruikt wordt.
Kan ik een module herladen nadat ik die heb bewerkt?
Ja, in een interactieve sessie gebruik je importlib.reload():
import importlib
import mymodule
importlib.reload(mymodule)
