1

I am writing an asynchronous python program that does many async functions, but unfortunately has to read a serial port, and serial is not async compatible, so I need to utilize a synchronous function to read the serial port, but don't want to block the async functions.

I have managed to complete this by doing:

import asyncio
import time

def serialReader():
    while True:
        print("waiting for new serial values")
        time.sleep(4)#simulated waiting on serial port
        return "some serial values"

async def func1():
    while True:
        print("function 1 running")
        await asyncio.sleep(1)

async def serialManager():
    loop = asyncio.get_running_loop()
    while True:
        result = await loop.run_in_executor(None, serialReader)
        print(result)

async def main(): 
    func1Task = asyncio.create_task(func1())
    func2Task = asyncio.create_task(serialManager())
    await func2Task


asyncio.run(main())

But my concern here is that I may be spawning multiple threads that will pile up eventually and cause problems. If this is a valid concern, is there a way to see the active threads?

MattG
  • 1,682
  • 5
  • 25
  • 45
  • I guess [`threading.active_count()`](https://docs.python.org/3/library/threading.html#threading.active_count) will give the number of active threads, not sure how well this works with async, I am also guessing the default executor that is used when you use `None` has a limit on the number of threads it can spawn – python_user Jun 02 '21 at 11:51
  • 1
    That seemed to work, it appears as though it stays at 3 active threads, which makes sense. Thanks! Put as answer if you like – MattG Jun 02 '21 at 12:20
  • Sure, I was hesitant as threading / async is not what I do regularly, but I have added an answer. :D – python_user Jun 02 '21 at 12:24
  • asyncio is cooperative multitasking - it uses coroutines and doesn't use threads. See https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work – DisappointedByUnaccountableMod Jun 02 '21 at 12:27
  • @barny wont `loop.run_in_exectuor` cause threads to be spawned? OP seems to get 3 active threads for this example – python_user Jun 02 '21 at 12:28
  • see also https://stackoverflow.com/questions/41204129/what-part-of-asyncio-is-concurrent-would-like-implementation-details/41208685#41208685 – DisappointedByUnaccountableMod Jun 02 '21 at 12:29
  • Yes, it seems to work as expected. I print `threading.active_count()` at the beginning and it returns 1, then I print after all 3 loops are running, and I get 3. Unless we are missing something? – MattG Jun 02 '21 at 12:35
  • @MattG I am guessing barny missed the part where you used an executor, as he mentions async is single threaded unless you specifically create one, which you might already know – python_user Jun 02 '21 at 12:37

1 Answers1

2

You can use threading.active_count() to get the number of active threads.

From Docs

Return the number of Thread objects currently alive. The returned count is equal to the length of the list returned by enumerate().

When you use None in loop.run_in_executor the default executor is used, which by default has a limit on the number of threads it can spawn.

python_user
  • 5,375
  • 2
  • 13
  • 32