9.1 Menedżery kontekstu
Pamiętasz, jak używaliśmy operatora with
, aby kontrolować dostęp do zasobu? Dzięki niemu mogliśmy dokładnie monitorować, kiedy zasób był używany, a kiedy ten proces się zakończył. To samo możemy zrobić dla „asynchronicznych zasobów”.
Asynchroniczne menedżery kontekstu (AsyncContextManager)
są używane do zarządzania zasobami w programowaniu asynchronicznym, zapewniając właściwe otwarcie i zamknięcie zasobów w funkcjach asynchronicznych. Działają analogicznie do zwykłych menedżerów kontekstu, ale są przeznaczone do użycia w funkcjach asynchronicznych z użyciem słów kluczowych async with
.
Nie będę o tym szczegółowo opowiadać, ponieważ na pewno w najbliższym czasie nie będziesz tworzyć własnych asynchronicznych menedżerów kontekstu, a do czasu, kiedy zdecydujesz się to zrobić, i tak wszystko zapomnisz. Ale chciałbym Cię zaznajomić z samą koncepcją.
Tworzenie asynchronicznego menedżera kontekstu
Asynchroniczne menedżery kontekstu definiuje się przy użyciu metod __aenter__
i __aexit__
. Te metody są analogiczne do metod __enter__
i __exit__
w zwykłych menedżerach kontekstu, ale są asynchroniczne.
-
__aenter__()
: Asynchroniczna metoda wywoływana przy wejściu do kontekstu. -
__aexit__(exc_type, exc, tb)
: Asynchroniczna metoda wywoływana przy wyjściu z kontekstu. Przyjmuje trzy argumenty: typ wyjątku, sam wyjątek i śledzenie(traceback)
.
Przykład tworzenia asynchronicznego menedżera kontekstu
import asyncio
class AsyncContextManager:
async def __aenter__(self):
print("Enter context")
return self
async def __aexit__(self, exc_type, exc, tb):
print("Exit context")
async def main():
async with AsyncContextManager():
print("Inside context")
asyncio.run(main())
Tak będzie wykonywany ten kod:
- Asynchronicznie uruchomi się funkcja
main()
- Funkcja
main()
zacznie się wykonywać - Utworzy się obiekt typu
AsyncContextManager
- Dla obiektu
AsyncContextManager
wywoła się metoda__aenter__()
- Zostanie wyświetlony
print("Enter context")
- Wykona się kod
print("Inside context")
- Dla obiektu
AsyncContextManager
wywoła się metoda__aexit__()
- Zakończy się wykonanie funkcji
main()
9.2 Przykłady użycia
W powyższym przykładzie nie jest konieczne używanie asynchronicznej wersji menedżera kontekstu — kod będzie działać, nawet jeśli go zrobimy synchronicznym.
Ale asynchroniczny menedżer jest potrzebny, jeśli wewnątrz bloku with
jest wywoływana funkcja asynchroniczna lub używany jest operator await
.
Asynchroniczny menedżer kontekstu do pracy z plikami
W tym przykładzie używana jest biblioteka aiofiles
do asynchronicznego odczytu i zapisu plików. Asynchroniczny menedżer kontekstu aiofiles.open
pozwala bezpiecznie otwierać i zamykać pliki w asynchronicznym kontekście.
import aiofiles
import asyncio
async def main():
async with aiofiles.open('example.txt', mode='w') as file:
await file.write('Hello, world!')
asyncio.run(main())
Asynchroniczny menedżer kontekstu do operacji sieciowych
W tym przykładzie używa się biblioteki aiohttp
do wykonywania asynchronicznych żądań HTTP. Asynchroniczne menedżery kontekstu ClientSession
i session.get
zapewniają właściwe zarządzanie połączeniami.
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
html = await fetch('https://example.com')
print(html)
asyncio.run(main())
Asynchroniczne menedżery kontekstu zapewniają automatyczne zarządzanie zasobami, takimi jak pliki, połączenia sieciowe i innymi zasobami, które muszą być otwierane i zamykane.
Metody __aenter__
i __aexit__
pozwalają na wykonywanie asynchronicznych operacji przy wejściu i wyjściu z kontekstu, zapewniając równoległe wykonywanie zadań. Korzystanie z asynchronicznych menedżerów kontekstu pomaga uniknąć wycieków zasobów i gwarantuje, że wszystkie zasoby zostaną poprawnie zwolnione.
GO TO FULL VERSION