Search code examples
pythonsocketspython-asynciotelethon

Telethon event handler not firing when used in an asyncio task with another task


I'm trying to get two tasks with infinite loops running simultaneously. One of them involves running the Telethon client indefinitely, the other involves a while loop in order to check for connections on a socket.

The socket task works fine, I can create the socket and connect a client to it. However the other task, which runs the Telethon client, doesn't seem to respond to the NewMessage event when I fire off an event from my telegram account. I've seen this working prior, so I know it's not the client itself, my account or the connection to it.

I assume this is just an issue with me not understanding how the asyncio package works. Could someone please point me in the right direction to understanding how I can have both of my tasks run concurrently and respond to both my socket and my message events.

client = TelegramClient('anon', api_id, api_hash)

@client.on(events.NewMessage)
async def onMessage(event):
    # print(event.raw_text) # Event handler implementation
    

async def run_client():
    await client.start()
    await client.run_until_disconnected()
    # async with client:
        # await client.run_until_disconnected()
        # await client.loop.run_forever()

async def socket_listener():
    global client_socket
    while True:
        # Accept a client connection
        client_socket, client_address = server_socket.accept()
        print("Client connected:", client_address)


async def main():    
    asyncio.gather(run_client(), socket_listener())

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


Solution

  • Your socket_listener has no await, which means it will never yield control back to the asyncio event loop. If the asyncio event loop doesn't get control back, it will be unable to progress your other tasks.

    In other words, server_socket.accept() is blocking the entire thread.

    You should use an asyncio alternative to listen to connections. See the documentation for asyncio Streams, in particular, asyncio.start_server, which is an async alternative.