Die meisten magischen Methoden sind nicht zur Arbeit entwickelt , um mit async def
/ await
- in der Regel sollten Sie nur verwenden werden await
innerhalb der dedizierten asynchronen magischen Methoden - __aiter__
, __anext__
, __aenter__
, und __aexit__
. Die Verwendung in anderen magischen Methoden funktioniert entweder überhaupt nicht, wie dies der Fall ist __init__
(es sei denn, Sie verwenden einige Tricks, die in anderen Antworten hier beschrieben sind), oder zwingt Sie, immer das zu verwenden, was den Aufruf der magischen Methode in einem asynchronen Kontext auslöst.
Bestehende asyncio
Bibliotheken können dies auf zwei Arten behandeln: Erstens habe ich das verwendete Factory-Muster gesehen ( asyncio-redis
zum Beispiel):
import asyncio
dsn = "..."
class Foo(object):
@classmethod
async def create(cls, settings):
self = Foo()
self.settings = settings
self.pool = await create_pool(dsn)
return self
async def main(settings):
settings = "..."
foo = await Foo.create(settings)
Andere Bibliotheken verwenden eine Coroutine-Funktion der obersten Ebene, die das Objekt erstellt, und keine Factory-Methode:
import asyncio
dsn = "..."
async def create_foo(settings):
foo = Foo(settings)
await foo._init()
return foo
class Foo(object):
def __init__(self, settings):
self.settings = settings
async def _init(self):
self.pool = await create_pool(dsn)
async def main():
settings = "..."
foo = await create_foo(settings)
Die create_pool
Funktion, von aiopg
der aus Sie aufrufen möchten, __init__
verwendet genau dieses Muster.
Dies behebt zumindest das __init__
Problem. Ich habe keine Klassenvariablen gesehen, die asynchrone Aufrufe in freier Wildbahn ausführen, an die ich mich erinnern kann, daher weiß ich nicht, dass etablierte Muster entstanden sind.
__new__
, obwohl es vielleicht nicht elegant ist