ProgrammierungPython-Entwickler (asyncio/Backend)

Was ist ein Async-Kontextmanager in Python, wie wird er implementiert und wo ist er unverzichtbar?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Ein Async-Kontextmanager ist ein Objekt, das die asynchronen Methoden __aenter__ und __aexit__ definiert und in der Konstruktion async with verwendet wird. Ein solcher Manager ist erforderlich, um Ressourcen in asynchronen Funktionen korrekt zu öffnen/schließen: Verbindungen zu Datenbanken, Dateien, Sitzungen usw.

Beispiel der Implementierung:

class AsyncDBConnection: async def __aenter__(self): self.conn = await async_db_connect() return self.conn async def __aexit__(self, exc_type, exc, tb): await self.conn.close() async def main(): async with AsyncDBConnection() as conn: await conn.query('SELECT 1')

Der asynchrone Kontext ermöglicht es, den Event-Loop durch technische Verzögerungen nicht zu blockieren, was die Leistung von Concurrent-Programmen verbessert.

Fangfrage.

Kann man ein normales with innerhalb von async def verwenden?

Antwort: Ja, aber wenn die Operationen innerhalb des Kontextmanagers awaitable sind (await erfordern), wird genau async with benötigt. Das normale with unterstützt keinen asynchronen Enter/Exit und blockiert den Event-Loop oder schlägt fehl, wenn await innerhalb von enter/exit aufgerufen wird.

Beispiel:

async def foo(): with open('file.txt') as f: # das ist ok, da das Lesen synchron ist data = f.read() # Aber await kann innerhalb eines normalen Kontexts nicht verwendet werden, nur innerhalb von async with

Beispiele realer Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

Projekt: Webdienst mit asynchroner API.

Problem: Der Verbindungsmanager zur Datenbank verwendete ein normales with, aber es wurde await aufgerufen. Dies führte zu einem Fehler RuntimeError("Cannot use 'await' outside async function") und blockierte den Event-Loop in der Produktion.


Geschichte

Projekt: Chat über Websockets.

Problem: Bei der Arbeit mit Verbindungen wurden Websocket-Ressourcen nicht geschlossen (es wurde ein normaler synchroner Manager verwendet), was zu Speicherlecks und hängenden Verbindungen führte.


Geschichte

Projekt: Multithreaded asynchrone Aufgabenwarteschlange.

Problem: Der Aufgabenmanager implementierte __aexit__ nicht korrekt und vergaß, awaitable zurückzugeben. Dadurch wurde der Abschluss der Aufgaben nicht garantiert, und einige Aufgaben „hingen“ im System.