17.8 Dekoratori
Dekorator možeš da zamisliš kao prečicu za primenu tzv wrapper funkcije. Wrapper funkcije su takve funkcije koje pozivaju neku drugu funkciju, a da pri tome one mogu da rade nešto svoje ili da ne rade ništa (tj, mogu da pripremaju „sirove“ podatke iz programa za format koji glavna funkcija očekuje i slično). U suštini dekoratori nam mogu biti korisni da bi smo "wrap" funkciju pozivali konstantno - sa istim delom programa, iznova i iznova dokle god se ne obavi potrebna obrada. Na primer, kreirao sam dekorator koji se zove ponovo, kako bih ga mogao primeniti na bilo kojoj funkciji, koji mi služi da, ukoliko se pojavi neka greška u radu, Python ne prekine izvršavanje programa, već da pokuša ponovno da pokrene funkciju, i to najviše 5 puta, sa malom pauzom između svakog novog pokušaja da obavi zadatak. Ovo može biti korisno u nekim situacijama, kao što su pokušaji uspostavljanja komunikacije sa računarom koji je negde na mreži (intrnetu):
#!/usr/bin/env python3
'''Skripta koja simulira pokušaj uspostavljanja komunikacije.'''
from time import sleep
from functools import wraps
import logging
logging.basicConfig()
log = logging.getLogger("ponovo")
def ponovo(f):
@wraps(f)
def wrapped_funkcija(*arg, **kvarg):
MAKS_POKUSAJ = 5
for pokusaj in range(1, MAKS_POKUSAJ + 1):
try:
return f(*arg, **kvarg)
except:
log.exception("Pokušaj %s/%s nije uspeo : %s",
pokusaj,
MAKS_POKUSAJ,
(arg, kvarg))
sleep(10 * pokusaj)
log.critical("Svi %s pokušaji su propali : %s",
MAKS_POKUSAJ,
(arg, kvarg))
return wrapped_funkcija
brojac = 0
@ponovo
def sacuvaj_u_bazu(arg):
print("Piši u bazu podataka ili uspostavi netvork konekciju itd.")
print("Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške.")
global brojac
brojac += 1
if brojac < 2:
raise ValueError(arg)
if __name__ == '__main__':
sacuvaj_u_bazu("Neka loša vrednost")
Što nam daje sledeći izlaz:
./pokusaj.py
Piši u bazu podataka ili uspostavi netvork konekciju itd.
Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške.
ERROR:ponovo:Pokušaj 1/5 nije uspeo : (('Neka loša vrednost',), {})
Traceback (most recent call last):
File "./pokusaj.py", line 18, in wrapped_funkcija
return f(*arg, **kvarg)
File "./pokusaj.py", line 39, in sacuvaj_u_bazu
raise ValueError(arg)
ValueError: Neka loša vrednost
CRITICAL:ponovo:Svi 5 pokušaji su propali : (('Neka loša vrednost',), {})
Piši u bazu podataka ili uspostavi netvork konekciju itd.
Ovo će se automatski ponovo izvršavati, ukoliko dođe do neke greške.
Ovo je malo napredan primer, ne moraš da ga znaš, ali je bitno da ga razumeš. Kao što vidiš, glavna funkcija nam je sacuvaj_u_bazu(). Budući da sam ispred nje koristio dekorator koji poziva funkciju ponovo() ovaj program pokušava da 5 puta izvrši glavnu funkciju. Obrati pažnju da je dekorator celu glavnu funkciju prosledio kao argument funkciji ponovo(), tj dekorator je uradio ovu stvar: ponovo(sacuvaj_u_bazu()). Za više informacija kako se radi sa dekoratorima pročitaj sadržaj koji se nalazi na ovom mestu.
17.7 assert naredba | Indeks | 17.9 Razlike između verzija |
0 Коментари
Pokažite nam šta mislite o ovome!