Search code examples
pythontkinterpython-asyncio

Running asyncio loop and tkinter gui


How do I run a asyncio loop running a while loop for websocket receiving and tkinter gui at the same time?

My current code: (without GUI)

I know how to write the code for tkinter gui but getting problems when compining them. When starting tkinter Mainloop the asyncio loop stops and disconnects from websocket. I also tried threading but hasent worked either.

import asyncio
import websockets
from aioconsole import ainput

queue = asyncio.Queue()


async def connect():
    global name
    try:
        async with websockets.connect("ws://ip:port") as websocket:
            print("Verbunden!")
            
            asyncio.get_running_loop().create_task(send(websocket))
            asyncio.get_running_loop().create_task(cli())

            while True:
                message = await websocket.recv()
                print(message)


    except:
        print("Fehler!")
        await asyncio.sleep(2)
        asyncio.get_running_loop().stop()


async def send(websocket):
    print("Sender gestartet!")
    global name
    while True:
        message = await queue.get()
        await websocket.send(message)


async def cli():
    print("Bereit für Eingabe!")
    while True:
        message = await ainput()
        await queue.put(message)



loop = asyncio.get_event_loop()
loop.create_task(connect())
loop.run_forever()

Solution

  • I have found a working solution using threading, asyncio and websockets:

    import tkinter
    import asyncio
    import threading
    import websockets
    from websockets import exceptions
    import json
    from datetime import datetime
    
    
    # Starthilfe für asynkrone Funktion connect
    def _asyncio_thread():
        async_loop.create_task(connect())
        async_loop.run_forever()
    
    
    async def connect():
        try:
            async with websockets.connect("ws://194.163.132.218:8765") as websocket:
                while True:
                    message = await websocket.recv()
                    print(message)
    
    
    async def send(websocket, name):
        while True:
            message = await queue.get()
            await websocket.send(msg)
    
    def buttonexecutor(e=None):
        msg = entry.get()
        asyncio.run_coroutine_threadsafe(messagesender(msg), async_loop)
        entry.delete(0, "end")
    
    
    async def messagesender(message):
        await queue.put(message)
    
    
    def logger(reason, message):
        now = datetime.now()
        current_time = now.strftime("%H:%M:%S")
        text.configure(state="normal")
        text.insert("end", f"({current_time}) [ {reason} ] {message}\n")
        text.configure(state="disabled")
    
    
    if __name__ == '__main__':
        # Asyncio
        async_loop = asyncio.get_event_loop()
        queue = asyncio.Queue()
    
        # Erstelle tkinter
        root = tkinter.Tk()
        root.title("Messanger")
    
        text = tkinter.Text(root, width=150, state="disabled")
        text.pack()
    
        entry = tkinter.Entry(root, state="disabled", width=100)
        entry.pack()
    
        tkinter.Button(master=root, text="Senden", command=buttonexecutor).pack()
    
        # Starte Websocket Verbindung
        thread = threading.Thread(target=_asyncio_thread).start()
    
        # Starte tkinter
        root.mainloop()