如何在线程中使用telethon

时间:2018-01-12 11:34:30

标签: python django telethon

我想在后台运行一个函数。所以我在我的代码中使用了线程。

但返回错误ValueError: signal only works in main thread并且不了解两件事:

  1. 什么是主线程
  2. 如何解决这个问题:)
  3. views.py

    def callback(update):
        print('I received', update)
    
    def message_poll_start():
        try:
            client = TelegramClient('phone', api_id, api_hash,
                update_workers=1, spawn_read_thread=False)
            client.connect()
            client.add_update_handler(callback)
            client.idle()
        except TypeNotFoundError:
            pass
    
    def message_poll_start_thread(request):
        t = threading.Thread(target=message_poll_start, args=(), kwargs={})
        t.setDaemon(True)
        t.start()
        return HttpResponse("message polling started")
    

    urls.py

    urlpatterns = [
        path('message_poll_start', messagemanager_views.message_poll_start_thread, name="message_poll_start"),
    ]
    

    trace

    [12/Jan/2018 11:24:38] "GET /messages/message_poll_start HTTP/1.1" 200 23
    Exception in thread Thread-3:
    Traceback (most recent call last):
      File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
        self.run()
      File "/usr/lib/python3.5/threading.py", line 862, in run
        self._target(*self._args, **self._kwargs)
      File "/home/teletogram/telethogram/messagemanager/views.py", line 123, in message_poll_start
        client0.idle()
      File "/home/teletogram/.env/lib/python3.5/site-packages/telethon/telegram_bare_client.py", line 825, in idle
        signal(sig, self._signal_handler)
      File "/usr/lib/python3.5/signal.py", line 47, in signal
        handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
    ValueError: signal only works in main thread
    

1 个答案:

答案 0 :(得分:0)

1)默认情况下,python脚本在主线程中运行。如果使用threading.Thread产生一个新线程,则将创建一个与主线程分开运行的新线程。当我开始学习线程时,我花了很多时间阅读,然后才开始单击。官方threading docs的基本功能不错,我喜欢this tutorial进行更深入的了解。

2)Telethon的内部依赖于asyncio。在异步中,每个线程都需要有自己的异步事件循环,因此,产生的线程需要显式创建的事件循环。像线程一样,asyncio是一个大话题,Telethon docs中涵盖了其中的一些话题。

类似的事情应该起作用:

import asyncio
def message_poll_start():
    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        client = TelegramClient('phone', api_id, api_hash, loop=loop)
        client.connect()
        client.add_update_handler(callback)
        client.idle()
    except TypeNotFoundError:
        pass