Mooduli käivitamine skriptina

PyCharmis on moodulite töölepanek lihtne, tuleb lihtsalt vajutada nuppu Run. Terminalist tuleb skripti käivitamiseks kirjutada käsureale python faili_nimi.py <argumendid>.

Näitena loodud moodul fibo.py Fibonacci numbrite arvutamiseks:

"""Fibonacci numbers module."""
import sys


def fib(n):
    """Calculate the n-th fibonacci number."""

    if n == 0:
        return 0
    if n == 1:
        return 1
    fibo_prev, fibo = 0, 1
    for _ in range(2, n + 1):
        fibo_prev, fibo = fibo, fibo_prev + fibo
    return fibo


if __name__ == '__main__':
    print(fib(int(sys.argv[1])))

Olles käsureal samas kaustas, kus asub moodul fibo.py, saame käivitada skripti nt argumendiga 15.

C:\>python fibo.py 15
610

Mooduli importimisel käivitatakse seal olev kood. Kui me tahame midagi käima panna skriptina, siis tasub mooduli lõppu panna järgnev kood:

if __name__ == "__main__":
    pass

__name__ on spetsiaalne muutuja, mis määratakse koodile käima panemisel. Kui skript pannakse otse tööle, siis saab muutuja __name__ väärtuse "__main__". Importimisel saab muutuja väärtuseks mooduli nime.

Vaatame, mis juhtub, kui seda koodijuppi näiteks ei kasuta. Olgu meil olemas moodul dice.py, mis veeretab täringuid:

"""Dice rolling module."""

from random import randint


def dice_roll():
    return randint(1, 6)


def roll_two_dices():
    return dice_roll() + dice_roll()


print("Rolling a dice...")
print(f"The value is: {dice_roll()}")

Paneme selle programmi käsurealt tööle. Kuna argumente pole vaja edastada, siis pole sys moodulit vaja sisse tuua.

C:\>python dice.py
Rolling a dice...
The value is: 4

Tundub, et kõik töötab nii nagu vaja ja tulemus prinditi konsooli.

Nüüd aga soovime me simuleerida täringu viskeid suuremas koguses. Loome mooduli simulation.py:

"""A dice simulation module."""

import sys
from pprint import pprint

from dice import roll_two_dices


def simulate_rolls(n):
    """Print the count of each two dice roll
    value after n rolls."""
    d = {}
    for _ in range(n):
        v = roll_two_dices()
        d[v] = d.get(v, 0) + 1
    print(f"Simulating {n} rolls...")
    pprint(d)


simulate_rolls(int(sys.argv[1]))

Siin anname käsurealt tööle pannes juurde ka ühe argumendi. Käivitame terminalist skripti andes selle argumendiks 1000.

C:\>python simulation.py 1000
Rolling a dice...
The value is: 2
Simulating 1000 rolls...
{2: 24,
 3: 59,
 4: 80,
 5: 110,
 6: 139,
 7: 150,
 8: 138,
 9: 111,
 10: 83,
 11: 70,
 12: 36}

Mis nüüd juhtus? Käivitusid mooduli dice.py print käsud. Mooduli importimisel pannakse kogu kood tööle. Tahame, et mõlemat moodulit saaks skriptina käivitada, aga samas saaks ka importida ilma, et käivituks printimise käsud. Just selleks ongi olemas __main__.

Uuendades moodulit dice.py, käivituvad print käsud ainult juhul, kuid dice.py käivitatakse otse skriptina. Importimisel need enam tööle ei lähe.

"""Dice rolling module."""

from random import randint


def dice_roll():
    return randint(1, 6)


def roll_two_dices():
    return dice_roll() + dice_roll()


if __name__ == '__main__':
    print("Rolling a dice...")
    print(f"The value is: {dice_roll()}")