1

I have a simple python tkinter gui with just a couple buttons. When the button is pressed all I want to do is start a websocket connection and start receiving. I can run the code normally but as soon as I try to put it into a thread I get errors

RuntimeError: There is no current event loop in thread

So first try:

import websockets
websocket = websockets.connect(uri, ssl = True)
websocket.recv()

I get the error

"Connect object has no attribute 'recv'"

Which is weird when I run it differently I don't get that error When I follow the documentation exactly

   def run_websockets2(self):
        async def hello():
            uri = Websocket_Feed
            # with websockets.connect(uri, ssl=True) as websocket:
            socket = await websockets.connect(uri, ssl=True)
            self.web_socket = socket
            while self.running:
                greeting = await socket.recv()
                print(f"< {greeting}")
        asyncio.get_event_loop().run_until_complete(hello())

It works as long as I just call "websockets2()". But if I try to do

self.websocket_thread = threading.Thread(target=self.run_websockets2, args=())
self.websocket_thread.start()

I get the error

RuntimeError: There is no current event loop in thread 'web_sockets'

And when I make the whole function non async I get an error

def run_websockets(self):
    uri = Websocket_Feed
    # with websockets.connect(uri, ssl=True) as websocket:
    socket = websockets.connect(uri, ssl=True)
    self.web_socket = socket
    while self.running:
        greeting = socket.recv()
        print(f"< {greeting}")

I get the error RuntimeError: There is no current event loop in thread 'web_sockets'. on socket = websockets.connect(uri, ssl=True)

I don't understand why I can't just simply run these non asynchronous in a thread. Any help is greatly appreciated

2 Answers 2

3

You have a couple of different errors here, which is confusing the picture somewhat. First, regarding:

 "Connect object has no attribute 'recv'"

... this just says that websocket object has no method called recv

The main problem you have is trying to invoke run_websockets2() from a spawned thread. I.e. calling this method from main thread works, but calling this from a new thread fails.

This is expected behaviour. It is because in a spawned thread (i.e., thread other than main thread), there is no asyncio event loop defined. But there is one defined in the main thread, for convenience. So asyncio is aware of whether you are invoking from spawned thread, or main thread, and behaves differently. See this answer for detailed explantion. Why asyncio.get_event_loop method checks if the current thread is the main thread?

To solve your problem you could create a new event loop per spawned thread, so that the code would become:

event_loop = asyncio.new_event_loop()
event_loop.run_until_complete(hello())

instead of

asyncio.get_event_loop().run_until_complete(hello())

Or, you could store event_loop in a common place, and allow all spawned threads to reuse that event loop.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Darren Smith. I think it is weird the way pthon behaves in this context but your answer was the correct one. I didn't know thats how async stuff worked.
3

I wanted to post how I actually solved my code thanks to @Darren Smith. I simply added one line of code "asyncio.set_event_loop(asyncio.new_event_loop())" to the top.

 def run_websockets2(self):
        asyncio.set_event_loop(asyncio.new_event_loop())

        async def hello():
            uri = Websocket_Feed
            # with websockets.connect(uri, ssl=True) as websocket:
            socket = await websockets.connect(uri, ssl=True)
            self.web_socket = socket
            while self.running:
                greeting = await socket.recv()
                print(f"< {greeting}")

        asyncio.get_event_loop().run_until_complete(hello())

I have to admit, I love python, but to have code that fundamentally runs differently depending on its context and the fix is a one line that is not related to the context seems to be in really bad form.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.