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
AsyncContextManagerwywoła się metoda__aenter__() - Zostanie wyświetlony
print("Enter context") - Wykona się kod
print("Inside context") - Dla obiektu
AsyncContextManagerwywoł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