mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-24 18:33:44 +03:00
Add check for asyncio event loop to remain the same
This commit is contained in:
parent
6a7a981b7a
commit
16122545ec
|
@ -261,6 +261,46 @@ same session anywhere else. If you need to use the same account from
|
|||
multiple places, login and use a different session for each place you need.
|
||||
|
||||
|
||||
What does "The asyncio event loop must not change after connection" mean?
|
||||
=========================================================================
|
||||
|
||||
Telethon uses ``asyncio``, and makes use of things like tasks and queues
|
||||
internally to manage the connection to the server and match responses to the
|
||||
requests you make. Most of them are initialized after the client is connected.
|
||||
|
||||
For example, if the library expects a result to a request made in loop A, but
|
||||
you attempt to get that result in loop B, you will very likely find a deadlock.
|
||||
To avoid a deadlock, the library checks to make sure the loop in use is the
|
||||
same as the one used to initialize everything, and if not, it throws an error.
|
||||
|
||||
The most common cause is ``asyncio.run``, since it creates a new event loop.
|
||||
If you ``asyncio.run`` a function to create the client and set it up, and then
|
||||
you ``asyncio.run`` another function to do work, things won't work, so the
|
||||
library throws an error early to let you know something is wrong.
|
||||
|
||||
Instead, it's often a good idea to have a single ``async def main`` and simply
|
||||
``asyncio.run()`` it and do all the work there. From it, you're also able to
|
||||
call other ``async def`` without having to touch ``asyncio.run`` again:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# It's fine to create the client outside as long as you don't connect
|
||||
client = TelegramClient(...)
|
||||
|
||||
async def main():
|
||||
# Now the client will connect, so the loop must not change from now on.
|
||||
# But as long as you do all the work inside main, including calling
|
||||
# other async functions, things will work.
|
||||
async with client:
|
||||
....
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
|
||||
Be sure to read the ``asyncio`` documentation if you want a better
|
||||
understanding of event loop, tasks, and what functions you can use.
|
||||
|
||||
|
||||
What does "bases ChatGetter" mean?
|
||||
==================================
|
||||
|
||||
|
|
|
@ -399,6 +399,7 @@ class TelegramBaseClient(abc.ABC):
|
|||
self._borrowed_senders = {}
|
||||
self._borrow_sender_lock = asyncio.Lock()
|
||||
|
||||
self._loop = None # only used as a sanity check
|
||||
self._updates_error = None
|
||||
self._updates_handle = None
|
||||
self._keepalive_handle = None
|
||||
|
@ -535,6 +536,11 @@ class TelegramBaseClient(abc.ABC):
|
|||
if self.session is None:
|
||||
raise ValueError('TelegramClient instance cannot be reused after logging out')
|
||||
|
||||
if self._loop is None:
|
||||
self._loop = helpers.get_running_loop()
|
||||
elif self._loop != helpers.get_running_loop():
|
||||
raise RuntimeError('The asyncio event loop must not change after connection (see the FAQ for details)')
|
||||
|
||||
if not await self._sender.connect(self._connection(
|
||||
self.session.server_address,
|
||||
self.session.port,
|
||||
|
|
|
@ -30,6 +30,10 @@ class UserMethods:
|
|||
return await self._call(self._sender, request, ordered=ordered)
|
||||
|
||||
async def _call(self: 'TelegramClient', sender, request, ordered=False, flood_sleep_threshold=None):
|
||||
if self._loop is not None and self._loop != helpers.get_running_loop():
|
||||
raise RuntimeError('The asyncio event loop must not change after connection (see the FAQ for details)')
|
||||
# if the loop is None it will fail with a connection error later on
|
||||
|
||||
if flood_sleep_threshold is None:
|
||||
flood_sleep_threshold = self.flood_sleep_threshold
|
||||
requests = (request if utils.is_list_like(request) else (request,))
|
||||
|
|
Loading…
Reference in New Issue
Block a user