Arman Babaei
Arman Babaei

Reputation: 184

How to run a thread alongside telethon client

I'm willing to send some messages using telethon based on time, my approach was to write a function and start it in a new thread and check what messages I have to send each second. i.e. something like below:

async def function():
  while True:
    time = datetime.datetime.now()
    await send_some_messages(time)

but telethon needs me to await on the same loop as it is running. I know that I can get the current loop with client.run_until_disconnected(), but I'm confused how can I do this.

It'd be great if you could give me an approach to run this function in a different thread, but still be able to send messages using the telethon client.

Upvotes: 4

Views: 8136

Answers (2)

Manualmsdos
Manualmsdos

Reputation: 1545

client.run_until_disconnected() blocks!

If you need both the handler and the main function to work, do something like this:

# Get event loop
loop = asyncio.get_event_loop() 

# Create client
client = TelegramClient(..., loop=loop)
client.start()

# Do whatever with the client
@client.on(...)
async def handler(event):
    ...

async def main():
    while True:
        # Do whatever (check if now is time to send messages, for example)
        ...

        # Yielding control back to the event loop here (with `await`) is key.
        # We're giving an entire second to it to do anything it needs like
        # handling updates, performing I/O, etc.
        await asyncio.sleep(1)

loop.create_task(main())

client.run_until_disconnected()
loop.close()

Upvotes: 2

Lonami
Lonami

Reputation: 7076

You don't need to use threads when you're working with asyncio, and you also don't have to use client.run_until_disconnected(). All that does is keep the event loop running until the client is disconnected. As long as you run the event loop, Telethon will work just fine.

# Create client
client = ...

# Do whatever with the client
@client.on(...)
async def handler(event):
    ...

async def main():
    while True:
        # Do whatever (check if now is time to send messages, for example)
        ...

        # Yielding control back to the event loop here (with `await`) is key.
        # We're giving an entire second to it to do anything it needs like
        # handling updates, performing I/O, etc.
        await asyncio.sleep(1)

client.loop.run_until_complete(main())

Other ways to keep the event loop running are using loop.run_forever, and don't forget you can asyncio.create_task or wait on many of them… I encourage you to read the asyncio docs. Just like threading, the documentation is worth checking out to learn how to use it.


As a side note, if you really need threads (for example, you're doing CPU intensive work), asyncio also has your back covered. But none of this is really specific to Telethon.

If you want to get a better understanding on how asyncio works (maybe that helps you) see An Introduction to Asyncio

Needless to say, there are better ways to check when it's time to send messages (using a heap and events, sleeping until the next time is due or another maximum and not just one second), but this should get you started.

Upvotes: 9

Related Questions