Python asyncio und ContextVar

Python 3.7 fügte das Kontextvars-Modul (https://docs.python.org/ja/3/library/contextvars.html) hinzu und führte die ContextVar-Klasse für Asyncio ein.

Wie Thread Local (in Python threading.local ()), das eindeutige Daten für jeden Thread enthalten kann Darüber hinaus besteht die Funktion von ContextVar darin, dass jedes Collout eindeutige Daten enthalten kann.

Als ich ContextVar tatsächlich verwendete, stieß ich auf das Phänomen, dass der Datensatz in ContextVar verschwand. Daher schrieb ich erneut einen Bestätigungscode und untersuchte das Verhalten.

Im folgenden Code führen wir zwei Collout-Funktionen aus, "parent_await_coroutine ()" und "parent_create_new_task ()", und setzen in jeder Funktion den Wert auf ContextVar und rufen die Funktion "child ()" auf. Diese child () Funktion ändert den von ContextVar abgerufenen Wert.

Die beiden übergeordneten Funktionen rufen die untergeordnete Funktion unterschiedlich auf. Ersteres wartet auf die Coroutine und letzteres erstellt und führt eine neue Aufgabe aus, die die Coroutine umschließt.

Bei der Ausführung als letztere neue Aufgabe werden einige der Änderungen, die an der ContextVar in der untergeordneten Funktion vorgenommen wurden, nicht in der übergeordneten Funktion wiedergegeben. Insbesondere fügt die untergeordnete Funktion den Wert von number_var ContextVar hinzu und setzt ihn zurück, aber die übergeordnete Funktion liest die Änderung nicht (wie vor dem Aufruf der untergeordneten Funktion). Andererseits sind Änderungen an den ContextVar-Objekten msg_var to Msg auch für die übergeordnete Funktion sichtbar.

Dies liegt daran, dass der Inhalt von Kontextvars beim Erstellen der neuen Aufgabe kopiert wurde. Sie können dies aus PEP 567 lesen. Wenn bei diesem Kopiervorgang int von "number_var" int ist, wird der Wert kopiert und auf das Msg-Objekt von "msg_var" wird kopiert (d. H. Flache Kopie), sodass davon ausgegangen wird, dass das obige Verhalten ausgeführt wird. ..

import asyncio
import contextvars


class Msg:
    """Nur eine Textcontainerklasse.
Wird verwendet, um die flache Kopie von Kontextvars zu überprüfen.
    """

    def __init__(self, text: str):
        self._text = text

    @property
    def text(self) -> str:
        return self._text

    @text.setter
    def text(self, val):
        self._text = val


msg_var: contextvars.ContextVar[Msg] = contextvars.ContextVar('msg_var')
number_var: contextvars.ContextVar[int] = contextvars.ContextVar('number_var')


async def child():
    #Holen Sie sich die Nummer von ContextVar und fügen Sie 1 hinzu
    n = number_var.get()
    print(f'child: number={n}')  # child: number=1
    n += 1
    number_var.set(n)

    #Holen Sie sich das Msg-Objekt aus ContextVar und ändern Sie den Text
    msg = msg_var.get()
    print(f'child: msg="{msg.text}"')  # child: msg="msg created by parent"
    msg.text = 'msg changed by child'

    #Dieses Kind()Verarbeitung zur Ausführung der asynchronen Funktion
    await asyncio.sleep(0.1)


async def parent_await_coroutine():
    n = 1
    number_var.set(n)
    m = Msg('msg created by parent')
    msg_var.set(m)
    print(f'parent: number={n}')  # parent: number=1
    print(f'parent: msg="{m.text}"')  # parent: msg="msg created by parent"

    await child()

    n = number_var.get()
    m = msg_var.get()
    print(f'parent: number={n}')  # parent: number=2
    print(f'parent: msg="{m.text}"')  # parent: msg="msg changed by child"


async def parent_create_new_task():
    n = 1
    number_var.set(n)
    m = Msg('msg created by parent')
    msg_var.set(m)
    print(f'parent: number={n}')  # parent: number=1
    print(f'parent: msg="{m.text}"')  # parent: msg="msg created by parent"

    await asyncio.create_task(child())

    n = number_var.get()
    m = msg_var.get()
    print(f'parent: number={n}')  # parent: number=1
    print(f'parent: msg="{m.text}"')  # parent: msg="msg changed by child"


if __name__ == '__main__':
    asyncio.run(parent_create_new_task())
    asyncio.run(parent_await_coroutine())

Recommended Posts

Python asyncio und ContextVar
[Python] Komprimieren und dekomprimieren
Python- und Numpy-Tipps
[Python] Pip und Wheel
Python Iterator und Generator
Python-Pakete und -Module
Vue-Cli- und Python-Integration
Ruby, Python und Map
Python-Eingabe und Ausgabe
Python und Ruby teilen sich
Programmieren mit Python und Tkinter
Ver- und Entschlüsselung mit Python
Python: Klassen- und Instanzvariablen
3-3, Python-Zeichenfolge und Zeichencode
Python und Hardware-Verwenden von RS232C mit Python-
Python auf Ruby und wütend Ruby auf Python
Python-Einzug und String-Format
Python Real Number Division (/) und Integer Division (//)
Installieren Sie Python und Flask (Windows 10)
Informationen zu Python-Objekten und -Klassen
Informationen zu Python-Variablen und -Objekten
Apache mod_auth_tkt und Python AuthTkt
Å (Ongustorome) und NFC @ Python
Lernen Sie Python-Pakete und -Module kennen
# 2 [python3] Trennung und Kommentar aus
Flache Python-Kopie und tiefe Kopie
Python und Ruby Slice Memo
Python-Installation und grundlegende Grammatik
Ich habe Java und Python verglichen!
Flache Python-Kopie und tiefe Kopie
Über Python, len () und randint ()
Installieren Sie Python 3.7 und Django 3.0 (CentOS)
Python-Klassen- und Instanzvariablen
Ruby- und Python-Syntax ~ branch ~
[Python] Python und Sicherheit - is Was ist Python?
Stapel und Warteschlange in Python
Python-Metaklasse und SQLalchemie deklarativ
Implementierung von Fibonacci und Primzahlen (Python)
Python-Grundlagen: Bedingungen und Iterationen
Python-Bitoperator und logische Summe
Python-Debug- und Testmodul
Python-Liste und Tapples und Kommas
Python-Variablen und Objekt-IDs
Python-Listeneinschlussnotation und Generator
Über Python und reguläre Ausdrücke
Python mit Pyenv und Venv
Unittest und CI in Python
[Python] Quotient und Überschuss erhalten
Python 3 Sortier- und Vergleichsfunktionen
[Python] Suche nach Tiefenpriorität und Suche nach Breitenpriorität
Identität und Äquivalenz: ist und == in Python
Quellinstallation und Installation von Python
Python oder und und Operatorfalle
Fordern Sie Python3 und Selenium Webdriver heraus
Informationen zu Python- und Betriebssystemoperationen
Funktionen höherer Ordnung und Einschlussnotation in Python
Python (Python 3.7.7) Installation und grundlegende Grammatik
Python # Über Referenz und Kopie
Funktioniert mit Python und R.