Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use telethon in a thread

I want to run a function in background. so I use Threading in my code.

but return error ValueError: signal only works in main thread and don't know about two things:

  1. what is the main thread
  2. how to solve this problem :)

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
like image 653
Ehsan Avatar asked Jan 12 '18 11:01

Ehsan


1 Answers

1) A python script runs in the main thread by default. If you spawn a new thread using threading.Thread, that will create a new thread which runs separately from the main one. When I began learning about threading I spent a lot of time reading before it started to click. The official threading docs are decent for basic functionality, and I like this tutorial for a deeper dive.

2) The internals of Telethon rely on asyncio. In asyncio each thread needs its own asynchronous event loop, and thus spawned threads need an explicitly created event loop. Like threading, asyncio is a large topic, some of which is covered in the Telethon docs.

Something like this should work:

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
like image 178
Erock618 Avatar answered Oct 23 '22 05:10

Erock618