Comment utiliser async avec qui peut être utilisé à partir de python 3.5. PEP 492 -- Coroutines with async and await syntax
async with? Une version asynchrone du gestionnaire de contexte.
1.Faites une connexion à DB <-Il faut du temps = async 2. Faites quelque chose avec la connexion que vous avez établie 3. Fermez la connexion
Quand il y a un traitement comme
async with MyDB() as db:
db.do_something()
Si vous améliorez MyDB en exécutant le code, vous pouvez fermer automatiquement la connexion db lorsque vous quittez l'async avec block.
Par exemple, créons une classe qui enveloppe aiomysql et utilisons-la.
my_db.py
my_db.py
import asyncio
import aiomysql
class MyDB:
#Appelé juste avant d'entrer en mode asynchrone avec.
async def __aenter__(self):
loop = asyncio.get_event_loop()
self._connection = await aiomysql.connect(
host='localhost',
port=3306,
user='root',
password='ultrastrongpassword',
db='my_db',
charset='utf8',
loop=loop
)
return self
#Appelé immédiatement après avoir quitté l'asynchrone avec bloc.
async def __aexit__(self, exc_type, exc, tb):
self._connection.close()
async def fetchall(self, query, args=[]):
cursor = await self._connection.cursor()
await cursor.execute(query, args)
return await cursor.fetchall()
On a l'impression de cacher la destination de connexion de aiomysql.
Les plus importants sont «aenter» et «aexit». En les implémentant, cette classe peut être utilisée comme gestionnaire de contexte asynchrone. Le moment de l'appel est tel que commenté.
Comme dans l'exemple, aenter est un modèle courant pour configurer des ressources et aexit pour libérer des ressources.
Regardons également l'appelant.
Côté à utiliser
from my_db import MyDB
class Hoge:
async def call_db(self):
# db = MyDB()
# async with db:
#Mais cela a le même sens.
async with MyDB() as db:
result = db.fetchall('select * from some_table')
print(result)
Le format est ʻasynchronisation avec [instance de gestionnaire de contexte asynchrone] comme [valeur de retour de __aenter __]: `.
Lorsque cela est exécuté, le traitement se déroule dans l'ordre suivant.
__init__
est appelé)__aenter__
est appelé__aexit__
est appeléIl semble qu'une instance de base de données ne pourra utiliser toutes ses ressources que lorsqu'elle est asynchrone avec.
ʻAsync avec MyDB.connect () as db: `Quand vous voulez
Côté à utiliser
class Hoge:
async def call_db(self):
async with MyDB.connect() as db:
result = db.fetchall('select * from some_table')
print(result)
Implémentez simplement la méthode de connexion normalement comme suit:
my_db.py
class MyDB:
__slots__ = ['_connection']
async def __aenter__(self):
(Abréviation)
async def __aexit__(self, exc_type, exc, tb):
self._connection.close()
async def fetchall(self, query, args=[]):
(Abréviation)
@classmethod
def connect(cls):
return cls()
Tout ce dont vous avez besoin est une instance de MyDB (Asynchronous Context Manager) après asynchronisation avec.
Côté à utiliser
class Hoge:
async def call_db(self):
async with MyDB.direct_fetch('select * from some_table') as rows:
print(rows)
Dans ce cas, il est peu probable que la valeur de retour de MyDB.direct_fetch dans async with soit dans l'instance MyDB, vous devez donc réfléchir un peu. Get aiohttp peut être utile.
Il peut être géré en créant une classe de gestionnaire de contexte privé comme indiqué ci-dessous.
my_db.py
class _QueryContextManager:
def __init__(self, coro):
self._coro = coro
async def __aenter__(self):
loop = asyncio.get_event_loop()
self._connection = await aiomysql.connect(
host='localhost',
port=3306,
user='root',
password='ultrastrongpassword',
db='my_db',
charset='utf8',
loop=loop
)
return await self._coro(self._connection)
async def __aexit__(self, exc_type, exc, tb):
self._connection.close()
class MyDB:
__slots__ = ['_connection']
@classmethod
def direct_fetch(cls, query, args=[]):
async def fetch(connection):
cursor = await connection.cursor()
await cursor.execute(query, args)
return await cursor.fetchall()
#Renvoie un gestionnaire de contexte privé.
return _QueryContextManager(coro=fetch)
Hmm. Je ne peux pas nier le sentiment de force. .. Il existe peut-être une meilleure façon de l'écrire.
aiohttp peut fermer la connexion depuis l'instance de la valeur de retour de request (self._resp.release ()), donc cela semble être un peu plus propre.
Recommended Posts