Search on blog:

Python Jak uruchomić dwa procesy w tym samym czasie w asyncio

Problem jest jak uruchomić send_data() i read_data() w tym samym czasie w asyncio.

Nie można użyć run() do wystartowaniw dwóch procesów w tym samym czasie w asyncio. run() startuje jeden proces i czeka na jego zakończenie - tak więc run(send_data()) startuje funkcję send_data i czeka na jej zakończenie - i dlatego nie może uruchomić read_data. Jeśli zmienić kolejność to run(read_data()) będzie czekać na zakończenie read_data i nie uruchomi send_data

run() można użyc to uruchomienia funkcji, która użyje create_task() dla send_data() i read_data(). Należy najpierw stworzyć zadania a potem użyć ich z await ponieważ w przeciwnym przypadku nie wystartuje druga funkcjation

W przykładdzie w obu funkcjach jest użyte asyncio.sleep() aby w obu mieć jakąś funkcję z await.

import queue
import asyncio
import datetime

data_queue = queue.Queue()

async def send_data():
    print("send data")
    while True:
        data = str(datetime.datetime.now())
        print('put:', data)

        # add data to queue
        data_queue.put(data)

        await asyncio.sleep(2)

async def main():
    print("read data")
    while True:
        # read queued data from serial port
        if not data_queue.empty():
            data = data_queue.get()
            print('get:', data)

        await asyncio.sleep(1) 

async def start():
    print("start")
    #await send_data()  # doesn't work
    #await read_data()  # doesn't work

    # I had to create all tasks before running
    task1 = asyncio.create_task(send_data())
    task2 = asyncio.create_task(read_data())

    # running task
    await task1
    await task2

asyncio.run(start())

Ale prostrzą metodą jest użycie asyncio.gather()

async def start():
    print("start")
    await asyncio.gather(
        send_data(),
        read_data(),
    )

Reszta jest taka sama w poprzedniej wersji

import queue
import asyncio
import datetime

data_queue = queue.Queue()

async def send_data():
    print("send data")
    while True:
        data = str(datetime.datetime.now())
        print('put:', data)

        # add data to queue
        data_queue.put(data)

        await asyncio.sleep(2)

async def main():
    print("read data")
    while True:
        # read queued data from serial port
        if not data_queue.empty():
            data = data_queue.get()
            print('get:', data)

        await asyncio.sleep(1) 

async def start():
    print("start")
    await asyncio.gather(
        send_data(),
        read_data(),
    )

asyncio.run(start())

Notes:

Stackoverflow serial_asyncio: read serial port into a queue and read that queue from main() not working

BTW: Problem z queue:kiedy nie ma danych w kolejce queue wtedy get() może zablokować kod i lepiej jest sprawdzać czy kolejka nie jest pusta empty()

If you like it
Buy a Coffee