Reputation: 133
I have a network application which is listening on multiple sockets.
To handle each socket individually, I use Python's threading.Thread
module.
These sockets must be able to run tasks
on packet reception without delaying any further packet reception from the socket handling thread
.
To do so, I've declared the method(s) that are running the previously mentioned tasks
with the keyword async
so I can run them asynchronously with asyncio.run(my_async_task(my_parameters))
.
I have tested this approach on a single socket (running on the main thread
) with great success.
But when I use multiple sockets (each one with it's independent handler thread
), the following exception is raised:
ValueError: set_wakeup_fd only works in main thread
My question is the following: Is asyncio
the appropriate tool for what I need? If it is, how do I run an async
method from a thread that is not a main thread.
Most of my search results are including "event loops" and "awaiting" assync
results, which (if I understand these results correctly) is not what I am looking for.
I am talking about sockets in this question to provide context but my problem is mostly about the behaviour of asyncio
in child threads
.
I can, if needed, write a short code sample to reproduce the error. Thank you for the help!
Edit1, here is a minimal reproducible code example:
import asyncio
import threading
import time
# Handle a specific packet from any socket without interrupting the listenning thread
async def handle_it(val):
print("handled: {}".format(val))
# A class to simulate a threaded socket listenner
class MyFakeSocket(threading.Thread):
def __init__(self, val):
threading.Thread.__init__(self)
self.val = val # Value for a fake received packet
def run(self):
for i in range(10):
# The (fake) socket will sequentially receive [val, val+1, ... val+9]
asyncio.run(handle_it(self.val + i))
time.sleep(0.5)
# Entry point
sockets = MyFakeSocket(0), MyFakeSocket(10)
for socket in sockets:
socket.start()
Upvotes: 1
Views: 642
Reputation: 2076
This is possibly related to the bug discussed here: https://bugs.python.org/issue34679
If so, this would be a problem with python 3.8 on windows. To work around this, you could try either downgrading to python 3.7, which doesn't include asyncio.main so you will need to get and run the event loop manually like:
loop = asyncio.get_event_loop()
loop.run_until_complete(<your tasks>)
loop.close()
Otherwise, would you be able to run the code in a docker container? This might work for you and would then be detached from the OS behaviour, but is a lot more work!
Upvotes: 1