Python How to run two processes at the same time with asyncio
How to run send_data()
and read_data()
at the same time in asyncio
?
You can't use run()
to start two processes at the same time in asyncio.
run()
starts one process and it waits for its end - so run(send_data())
starts function send_data
and it waits for its end - and this way it never runs read_data
.
If you change order then run(read_data())
will wait for end of read_data
and it will never run send_data
You can use use run()
to start one function which uses create_task()
for send_data()
and read_data()
.
You have to first create tasks and later use them with await
because in other way it doesn't start second function read_data
.
In example in both functions I use asyncio.sleep()
to have some functions with 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())
But simpler method is to use asyncio.gather()
async def start():
print("start")
await asyncio.gather(
send_data(),
read_data(),
)
Rest is the same as in my previous code
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 with queue
: when there is no data in queue
then get()
may block code and it is better to check if it is not empty()