LonamiWebs / Telethon

Pure Python 3 MTProto API Telegram client library, for bots too!
https://docs.telethon.dev
MIT License
10.01k stars 1.41k forks source link

Using Telethon with Threads #1253

Closed Fleyderer closed 5 years ago

Fleyderer commented 5 years ago

Checklist

Code that causes the issue

from telethon.sync import TelegramClient
import ...
...

class TgWorker:

    def __init__(self, tg_id, tg_hash, number, session_name):
        self.client = TelegramClient(session_name, tg_id, tg_hash)
        self.client.start()

    def get_message(self, channel_id):
        channel = self.client.get_entity(channel_id)
        message = self.client.get_messages(channel, 1)
        return ...

class Worker(QThread):

    def __init__(...):
        self.tg = TgWorker(...)

    def get_info(...):
        message = self.tg.get_message(...)

    def run(...):
        info = self.get_info(...)

class App(QtWidgets.QMainWindow, gui.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.info_thread = Worker(...)  # creating new thread

    def start_thread_action(self):
        self.info_thread.start()

def main():
    app = QApplication(sys.argv)
    window = App()
    window.start_thread_action()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Traceback

Traceback (most recent call last):
  File "D:/Python/ProjectName/ProjectFile.py", line 577, in run
    info = self.get_info()
  File "D:/Python/ProjectName/ProjectFile.py", line 325, in get_info
    message = self.tg.get_message(...)
  File "D:/Python/ProjectName/ProjectFile.py", line 315, in get_message
    channel = self.client.get_entity(channel_id)
  File "D:\Python\Anaconda3\lib\site-packages\telethon\sync.py", line 35, in syncified
    loop = asyncio.get_event_loop()
  File "D:\Python\Anaconda3\lib\asyncio\events.py", line 678, in get_event_loop
    return get_event_loop_policy().get_event_loop()
  File "D:\Python\Anaconda3\lib\asyncio\events.py", line 584, in get_event_loop
    % threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Dummy-1'.

Yes, i know that Threads with Asyncio are not good, i've spent two days in search of solution. Previous solution i've found here was in using telethon-sync module, but then I've found information from you that it has been removed. In my app I have to use threads, because one is for user buttons, another is for bot, who's goal is to get last messages from telegram using client.

Firstly, i've tested code connected with only telethon in another file with only one thread, which is getting messages from channel and everything worked good.

Maybe, telethon-sync is available or maybe you know, what to change in this module. (i've tried to change some code in sync.py, but it was stupid solution with creating new loop and setting then. And ofc i've got error with starting new loop while another is running.

Thank you!

Lonami commented 5 years ago
  • [x] The error is in the library's code, and not in my own.

Why did you tick that box? It is not an error inside the library. Your code is faulty. You have to either learn by yourself how to mix threads and asyncio or learn basic asyncio (create several tasks…), because this problem does not require threads at all, and this is the wrong place to ask questions.

ftuyama commented 4 years ago

Why so rude? If someone has the same question: https://docs.telethon.dev/en/latest/concepts/asyncio.html?highlight=thread#can-i-use-threads

Lonami commented 4 years ago

Why so rude?

Sorry, could you explain how my comment above was rude in any way?

Nowhere in the message you can see a sign of disrespect. Only straight facts.

I'm also not sure why you've revived like 4 ancient issues on the topic when there has been no recent activity on them.

adbenitez commented 2 years ago

Why did you tick that box? It is not an error inside the library. Your code is faulty. You have to either learn by yourself how to mix threads and asyncio or learn basic asyncio (create several tasks…), because this problem does not require threads at all, and this is the wrong place to ask questions.

I think it is an issue in the library because it supposedly allows to use it in a sync way using from telethon.sync import TelegramClient I am trying to use Telethon in a complex project where pluggy lib is used and hooks are called from threads so I am not even intentionally using Telethon with a thread on my own, so it was a bit unexpected for me it fails with RuntimeError: There is no current event loop in thread more for devs that have not gone the async path yet and that is why we are using the telethon.sync stuff

at least it is worthy to clarify in the documentation that the sync functionality is rather pretty limited and can't be used with threads, thanks for your work!

Lonami commented 2 years ago

telethon.sync is a hack which I intend to remove in the future. It wraps every single async call on the library with loop.run_until_complete. The library still uses asyncio. There is a section in the docs, but you're welcome to send a PR to improve it.

In short, you can use threading with asyncio. But it is difficult and error-prone. There are answered questions elsewhere regarding this. The recommendation is to ditch threading if you can, or learn to use it properly before attempting.

adbenitez commented 2 years ago

thanks for the quick reply, I can't ditch threading so to solve the issue I will just use the normal async telethon api with a decorator to simplify the loop.run_until_complete stuff with a custom loop,

hope you are having a good weekend :)

Lonami commented 2 years ago

You can refer to How to use telethon in a thread. There are more questions in that site regarding threads, use of threadsafe queues to communicate with asyncio and so on. But as stated I would prefer to kep the issues section to actual issues.

Lonami commented 2 years ago

(Thanks for the kind words. Some of my comments a few years back were indeed rather harsh, but I believe I have grown better as a person since then, and have learned to be more gentle in the way I communicate.)

adbenitez commented 2 years ago

You can refer to How to use telethon in a thread. There are more questions in that site regarding threads, use of threadsafe queues to communicate with asyncio and so on. But as stated I would prefer to kep the issues section to actual issues.

btw, the pointed stackoverflow reply uses a loop parameter from TelegramClient constructor but the docstring says This argument is ignored. and indeed it seems to be ignored

(sadly I still haven't managed to properly use Telethon from sync code)

adbenitez commented 2 years ago

But as stated I would prefer to kep the issues section to actual issues.

asked a question about my issue with Telethon and Threads in https://stackoverflow.com/questions/74093209/telegram-does-not-send-authorization-code-if-the-request-was-sent-from-telethon