es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo manejar las variables de contexto en asyncio mientras se encuentran en un ciclo ‘while’?

El contexto de la variable ‘value’ no cambia a medida que pasa por el ciclo ‘while’.

”’

import contextvars 
import keyboard
import asyncio
import random

value = contextvars.ContextVar('value')
value.set('-')


async def q():
    while True:

        await asyncio.sleep(1)
        print(value.get())


async def s():
    while True:
        x = random.choice(list(range(10)))
        value.set(x)
        await asyncio.sleep(1)



async def main():
    t1 = asyncio.create_task(q())
    t2 = asyncio.create_task(s())

    await t1



asyncio.run(main())

La salida es ”—”. Quiero establecer un nuevo valor para esta variable de contexto, pero no puedo encontrar casos similares.

Es mi primera vez aquí, así que no sé si se muestran correctamente todas las imágenes y no sé cómo pegar un código aquí, así que por favor ayuda

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema parece estar relacionado con el hecho de que la variable de contexto value se establece dentro del bucle while True de la corutina s(), pero no se accede a ella dentro del mismo bucle. En cambio, se accede dentro del bucle while True de la corutina q(). Esto significa que el valor de value no cambiará hasta que la corutina s() ceda el control al bucle de eventos, lo cual ocurre cada vez que espera asyncio.sleep(1).

    Para demostrar esto, puedes modificar la corutina s() para que imprima el valor de value cada vez que lo establece:

    async def s():
        while True:
            x = random.choice(list(range(10)))
            value.set(x)
            print(f'se estableció el valor a {x}')
            await asyncio.sleep(1)
    

    Si ejecutas el código modificado, verás que la variable de contexto value se establece en un nuevo valor cada vez que se ejecuta la corutina s(), pero la salida de la corutina q() solo muestra el último valor establecido antes de que el bucle de eventos ceda el control:

    se estableció el valor a 9
    se estableció el valor a 3
    se estableció el valor a 2
    se estableció el valor a 3
    se estableció el valor a 5
    se estableció el valor a 1
    se estableció el valor a 0
    se estableció el valor a 8
    se estableció el valor a 6
    ---
    

    Para solucionar esto, podrías modificar la corutina q() para ceder el control al bucle de eventos cada vez que imprima el valor de value, agregando una instrucción await asyncio.sleep(0) antes de cada instrucción print:

    async def q():
        while True:
            await asyncio.sleep(1)
            await asyncio.sleep(0)  # ceder el control al bucle de eventos
            print(value.get())
    

    Con esta modificación, la salida de la corutina q() mostrará el valor actualizado de value cada vez que la corutina s() lo establezca:

    se estableció el valor a 6
    6
    se estableció el valor a 8
    8
    se estableció el valor a 9
    9
    se estableció el valor a 8
    8
    se estableció el valor a 3
    3
    se estableció el valor a 8
    8
    se estableció el valor a 9
    9
    se estableció el valor a 1
    1
    se estableció el valor a 0
    0
    

    Ten en cuenta que asyncio.sleep(0) se utiliza para ceder el control al bucle de eventos sin bloquear la corutina, lo que permite que se ejecuten otras corutinas en el ínterin. Sin ello, la corutina q() nunca cedería el control al bucle de eventos y la corutina s() nunca tendría la oportunidad de establecer el valor de value.

Comments are closed.