A with…as… szerkezetben alkalmazható kontextuskezelő fogalmát legtöbbször a fájlmegnyitással kapcsolatban szokták bevezetni, mert valóban ez talán a leggyakoribb használati eset. Mindazonáltal a kontextuskezelők sok más helyzetben is alkalmazhatók. Éppen ezért a Python tudásépítés lépésről lépésre című e-könyv „Kontextuskezelők” fejezete szándékosan nem fájlművelethez kötődő példákon keresztül vezeti be és tárgyalja a kontextuskezelők részleteit annak érdekében, hogy az olvasó elsődlegesen a koncepciót és a működési mechanizmust értse meg, amely birtokában utána már többféle probléma megoldására vetheti be ezt az érdekes és hasznos nyelvi szerkezetet.
Ebben a bejegyzésben most egy olyan példát mutatunk, amely a könyvben nem szerepel, hogy lássunk még egy, nem fájlműveleti alkalmazást. Az alábbi programsorokban futási idő mérésére szolgáló objektumokat hoztunk létre kontextuskezelőkkel, kétféle megvalósításban. Az egyik esetben egy osztályt definiáltunk, a másik esetben egy generátorfüggvényt dekoráltunk a szabványos könyvtár contextlib moduljában szereplő contextmanager függvénnyel. A tényleges időmérést a time modul perf_counter() függvényével hajtjuk végre.
A tesztelésnél mindkét időmérést végző kontextuskezelőt egy with utasítással használjuk, és a mérendő késleltetést a time modul sleep() függvényével állítjuk be. A két tesztkód közül az egyikben félidőben szándékosan egy kivételt keltünk, azért, hogy lássuk a kontextuskezelő helyes működését, vagyis azt, hogy ilyenkor is rendben lefut a mérés, és megkapjuk az kivételdobásig eltelt futási időt.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import time class Időmérő: def __enter__(self): self.start = time.perf_counter() return self def __exit__(self, exc_type, exc_val, exc_tb): stop = time.perf_counter() print(f'Futási idő: {(stop - self.start) * 1000:.1f} ms') return True # TESZT with Időmérő(): time.sleep(0.1) time.sleep(0.1) with Időmérő(): time.sleep(0.1) 1 / 0 time.sleep(0.1) # Eredmény: # Futási idő: 216.2 ms # Futási idő: 109.3 ms |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
from contextlib import contextmanager import time @contextmanager def időmérő(): start = time.perf_counter() try: yield except Exception as ex: pass # Vagy a pass helyett kivételkezelő utasítások. finally: stop = time.perf_counter() print(f'Futási idő: {(stop - start) * 1000:.1f} ms') # TESZT with időmérő(): time.sleep(0.1) time.sleep(0.1) with időmérő(): time.sleep(0.1) 1 / 0 time.sleep(0.1) # Eredmény: # Futási idő: 218.5 ms # Futási idő: 109.5 ms |