mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-28 12:23:45 +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.
|
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?
|
What does "bases ChatGetter" mean?
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,7 @@ class TelegramBaseClient(abc.ABC):
|
||||||
self._borrowed_senders = {}
|
self._borrowed_senders = {}
|
||||||
self._borrow_sender_lock = asyncio.Lock()
|
self._borrow_sender_lock = asyncio.Lock()
|
||||||
|
|
||||||
|
self._loop = None # only used as a sanity check
|
||||||
self._updates_error = None
|
self._updates_error = None
|
||||||
self._updates_handle = None
|
self._updates_handle = None
|
||||||
self._keepalive_handle = None
|
self._keepalive_handle = None
|
||||||
|
@ -535,6 +536,11 @@ class TelegramBaseClient(abc.ABC):
|
||||||
if self.session is None:
|
if self.session is None:
|
||||||
raise ValueError('TelegramClient instance cannot be reused after logging out')
|
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(
|
if not await self._sender.connect(self._connection(
|
||||||
self.session.server_address,
|
self.session.server_address,
|
||||||
self.session.port,
|
self.session.port,
|
||||||
|
|
|
@ -30,6 +30,10 @@ class UserMethods:
|
||||||
return await self._call(self._sender, request, ordered=ordered)
|
return await self._call(self._sender, request, ordered=ordered)
|
||||||
|
|
||||||
async def _call(self: 'TelegramClient', sender, request, ordered=False, flood_sleep_threshold=None):
|
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:
|
if flood_sleep_threshold is None:
|
||||||
flood_sleep_threshold = self.flood_sleep_threshold
|
flood_sleep_threshold = self.flood_sleep_threshold
|
||||||
requests = (request if utils.is_list_like(request) else (request,))
|
requests = (request if utils.is_list_like(request) else (request,))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user