Python: So verwenden Sie Async mit

Wie man Async damit benutzt, kann ab Python 3.5 verwendet werden. PEP 492 -- Coroutines with async and await syntax

async with? Eine asynchrone Version des Kontextmanagers.

  1. Stellen Sie eine Verbindung zur Datenbank her. <-Es dauert einige Zeit = asynchron
  2. Machen Sie etwas mit der Verbindung, die Sie hergestellt haben
  3. Schließen Sie die Verbindung

Wenn es Verarbeitung wie gibt

async with MyDB() as db:
    db.do_something()

Wenn Sie MyDB durch Ausführen des Codes verbessern, können Sie die Datenbankverbindung automatisch schließen, wenn Sie die asynchrone Verbindung mit block beenden.

Grundlegende Verwendung

Erstellen wir beispielsweise eine Klasse, die aiomysql umschließt, und verwenden Sie sie.

my_db.py

my_db.py


import asyncio
import aiomysql


class MyDB:
    #Wird kurz vor der Eingabe von async mit aufgerufen.
    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

    #Wird sofort nach dem Beenden des Async mit Block aufgerufen.
    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()

Es fühlt sich an, als würde man das Verbindungsziel von aiomysql verstecken.

Die wichtigsten sind "aenter" und "aexit". Durch die Implementierung dieser kann diese Klasse als asynchroner Kontextmanager verwendet werden. Der Zeitpunkt des Anrufs ist wie kommentiert.

Wie im Beispiel ist aenter ein gängiges Muster zum Einrichten von Ressourcen und aexit zum Freigeben von Ressourcen.

Benutzerseite

Schauen wir uns auch den Anrufer an.

Seite zu verwenden


from my_db import MyDB


class Hoge:
    async def call_db(self):
        # db = MyDB()
        # async with db:
        #Aber es hat die gleiche Bedeutung.
        async with MyDB() as db:
            result = db.fetchall('select * from some_table')
        print(result)

Das Format ist "asynchron mit [asynchroner Kontextmanager-Instanz] als [Rückgabewert von __aenter __]:".

Wenn dies ausgeführt wird, wird die Verarbeitung in der folgenden Reihenfolge fortgesetzt.

  1. Eine Instanz von MyDB wird erstellt (__init__ wird aufgerufen)
  2. Die asynchrone Klausel von Hoge beginnt mit der Verarbeitung
  3. MyDB __aenter__ wird aufgerufen
  4. Der Rückgabewert von __aenter__ von MyDB wird in db von async mit as db gespeichert
  5. Hoges result = db.fetchall ('select * from some_table') wird ausgeführt
  6. MyDB __aexit__ wird aufgerufen

Es scheint, dass eine Datenbankinstanz nur dann alle Ressourcen nutzen kann, wenn sie asynchron ist.

Verschiedene andere Verwendungen

Ich möchte es in der Fabrik verwenden

Wenn Sie so etwas wie "asynchron mit MyDB.connect () als db:" ausführen möchten

Seite zu verwenden


class Hoge:
    async def call_db(self):
        async with MyDB.connect() as db:
            result = db.fetchall('select * from some_table')
        print(result)

Implementieren Sie die Verbindungsmethode einfach wie folgt:

my_db.py


class MyDB:
    __slots__ = ['_connection']

    async def __aenter__(self):
        (Abkürzung)

    async def __aexit__(self, exc_type, exc, tb):
        self._connection.close()

    async def fetchall(self, query, args=[]):
        (Abkürzung)

    @classmethod
    def connect(cls):
        return cls()

Sie benötigen lediglich eine Instanz von MyDB (Asynchronous Context Manager) nach der Asynchronisierung mit.

Ich möchte mit einem System asynchronisieren, das meine eigene Instanz nicht zurückgibt

Seite zu verwenden


class Hoge:
    async def call_db(self):
        async with MyDB.direct_fetch('select * from some_table') as rows:
            print(rows)

In diesem Fall ist es unwahrscheinlich, dass sich der Rückgabewert von MyDB.direct_fetch in asynchroner Form mit in der MyDB-Instanz befindet. Sie müssen also ein wenig nachdenken. Get aiohttp kann hilfreich sein.

Sie können dies tun, indem Sie eine private Kontextmanagerklasse wie unten gezeigt erstellen.

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()

        #Gibt einen privaten Kontextmanager zurück.
        return _QueryContextManager(coro=fetch)

Hmm. Ich kann das Gefühl der Gewalt nicht leugnen. .. Es gibt vielleicht einen besseren Weg, es zu schreiben.

aiohttp kann die Verbindung von der Instanz des Rückgabewerts der Anforderung (self._resp.release ()) schließen, sodass sie etwas sauberer zu sein scheint.

Recommended Posts

Python: So verwenden Sie Async mit
python3: Verwendung der Flasche (2)
[Python] Verwendung von Liste 1
Wie benutzt man Python Argparse?
Python: Wie man pydub benutzt
[Python] Verwendung von checkio
[Python] Verwendung von input ()
Wie benutzt man Python Lambda?
[Python] Verwendung von virtualenv
python3: Verwendung der Flasche (3)
python3: Wie man eine Flasche benutzt
Verwendung von Python-Bytes
Wie man tkinter mit Python in Pyenv benutzt
[Python] Verwendung der Pandas-Serie
Verwendung von Anfragen (Python Library)
Verwendung von SQLite in Python
So verwenden Sie virtualenv mit PowerShell
Verwendung des interaktiven Python-Modus mit Git Bash
Erste Schritte mit Python
[Python] Verwendung von Liste 3 Hinzugefügt
Wie man MySQL mit Python benutzt
Verwendung der Python-API von OpenPose
Verwendung von ChemSpider in Python
Python: Verwendung von pydub (Wiedergabe)
Verwendung von PubChem mit Python
So berechnen Sie das Datum mit Python
Verwendung der Zip-Funktion von Python
[Python] Verwendung der Typetalk-API
Verwendung des Python-Wrappers PyRealsense von Realsense mit Jetson Nano
[Python] Zusammenfassung der Verwendung von Pandas
[Einführung in Python] Wie verwende ich eine Klasse in Python?
So installieren und verwenden Sie pandas_datareader [Python]
Verwendung von ManyToManyField mit Djangos Admin
Verwendung von OpenVPN mit Ubuntu 18.04.3 LTS
Verwendung von Cmder mit PyCharm (Windows)
[Python] Verwendung von __command__, Funktionserklärung
So arbeiten Sie mit BigQuery in Python
[Einführung in Python] Verwenden wir foreach mit Python
[Python] Verwendung von import sys sys.argv
Wie man Ass / Alembic mit HtoA benutzt
Verwendung von Japanisch mit NLTK-Plot
Wie man einen Taschentest mit Python macht
[Python] Organisieren der Verwendung für Anweisungen
Memorandum über die Verwendung von Gremlin Python
So zeigen Sie Python-Japanisch mit Lolipop an
[Python2.7] Zusammenfassung der Verwendung von unittest
Verwendung des Jupyter-Notebooks mit ABCI
Python: Verwendung von Einheimischen () und Globalen ()
Verwendung von __slots__ in der Python-Klasse
Verwendung des CUT-Befehls (mit Beispiel)
Verwendung von "deque" für Python-Daten
Wie man mit Python-Flüchen Japanisch eingibt
Verwendung von Python zip und Aufzählung
[Python] Verstehen, wie rekursive Funktionen verwendet werden
Zusammenfassung der Verwendung der Python-Liste
Verwendung regulärer Ausdrücke in Python
[Python2.7] Zusammenfassung der Verwendung des Unterprozesses
Verwendung ist und == in Python