Telethon/readthedocs/misc/compatibility-and-convenience.rst

188 lines
6.1 KiB
ReStructuredText
Raw Normal View History

2018-10-06 21:20:11 +03:00
.. _compatibility-and-convenience:
=============================
Compatibility and Convenience
=============================
Telethon is an `asyncio` library. Compatibility is an important concern,
2018-10-06 21:20:11 +03:00
and while it can't always be kept and mistakes happens, the :ref:`changelog`
is there to tell you when these important changes happen.
.. contents::
Compatibility
2019-05-09 13:24:37 +03:00
=============
2018-10-06 21:20:11 +03:00
2018-11-03 14:44:49 +03:00
Some decisions when developing will inevitable be proven wrong in the future.
One of these decisions was using threads. Now that Python 3.4 is reaching EOL
and using `asyncio` is usable as of Python 3.5 it makes sense for a library
2018-11-03 14:44:49 +03:00
like Telethon to make a good use of it.
2018-10-06 21:20:11 +03:00
2018-11-03 14:44:49 +03:00
If you have old code, **just use old versions** of the library! There is
nothing wrong with that other than not getting new updates or fixes, but
using a fixed version with ``pip install telethon==0.19.1.6`` is easy
enough to do.
2018-10-06 21:20:11 +03:00
2018-11-03 14:44:49 +03:00
You might want to consider using `Virtual Environments
<https://docs.python.org/3/tutorial/venv.html>`_ in your projects.
There's no point in maintaining a synchronous version because the whole point
is that people don't have time to upgrade, and there has been several changes
and clean-ups. Using an older version is the right way to go.
Sometimes, other small decisions are made. These all will be reflected in the
:ref:`changelog` which you should read when upgrading.
If you want to jump the `asyncio` boat, here are some of the things you will
2018-11-03 14:44:49 +03:00
need to start migrating really old code:
2018-10-06 21:20:11 +03:00
.. code-block:: python
2018-11-03 14:44:49 +03:00
# 1. Import the client from telethon.sync
from telethon.sync import TelegramClient
# 2. Change this monster...
try:
assert client.connect()
if not client.is_user_authorized():
client.send_code_request(phone_number)
me = client.sign_in(phone_number, input('Enter code: '))
... # REST OF YOUR CODE
finally:
client.disconnect()
2018-10-06 21:20:11 +03:00
# ...for this:
2018-11-03 14:44:49 +03:00
with client:
... # REST OF YOUR CODE
2018-10-06 21:20:11 +03:00
# 3. client.idle() no longer exists.
# Change this...
client.idle()
# ...to this:
client.run_until_disconnected()
# 4. client.add_update_handler no longer exists.
# Change this...
client.add_update_handler(handler)
# ...to this:
client.add_event_handler(handler)
2018-11-03 14:44:49 +03:00
In addition, all the update handlers must be ``async def``, and you need
to ``await`` method calls that rely on network requests, such as getting
the chat or sender. If you don't use updates, you're done!
2018-10-06 21:20:11 +03:00
Convenience
2019-05-09 13:24:37 +03:00
===========
2018-10-06 21:20:11 +03:00
.. note::
The entire documentation assumes you have done one of the following:
.. code-block:: python
from telethon import TelegramClient, sync
# or
from telethon.sync import TelegramClient
This makes the examples shorter and easier to think about.
For quick scripts that don't need updates, it's a lot more convenient to
forget about `asyncio` and just work with sequential code. This can prove
2018-11-03 14:44:49 +03:00
to be a powerful hybrid for running under the Python REPL too.
2018-10-06 21:20:11 +03:00
.. code-block:: python
from telethon.sync import TelegramClient
# ^~~~~ note this part; it will manage the asyncio loop for you
with TelegramClient(...) as client:
print(client.get_me().username)
# ^ notice the lack of await, or loop.run_until_complete().
# Since there is no loop running, this is done behind the scenes.
#
message = client.send_message('me', 'Hi!')
import time
time.sleep(5)
message.delete()
# You can also have an hybrid between a synchronous
# part and asynchronous event handlers.
#
from telethon import events
@client.on(events.NewMessage(pattern='(?i)hi|hello'))
async def handler(event):
await event.reply('hey')
client.run_until_disconnected()
Some methods, such as ``with``, ``start``, ``disconnect`` and
``run_until_disconnected`` work both in synchronous and asynchronous
contexts by default for convenience, and to avoid the little overhead
it has when using methods like sending a message, getting messages, etc.
This keeps the best of both worlds as a sane default.
.. note::
As a rule of thumb, if you're inside an ``async def`` and you need
the client, you need to ``await`` calls to the API. If you call other
functions that also need API calls, make them ``async def`` and ``await``
them too. Otherwise, there is no need to do so with this mode.
Speed
2019-05-09 13:24:37 +03:00
=====
2018-10-06 21:20:11 +03:00
When you're ready to micro-optimize your application, or if you simply
don't need to call any non-basic methods from a synchronous context,
2018-11-03 14:44:49 +03:00
just get rid of ``telethon.sync`` and work inside an ``async def``:
2018-10-06 21:20:11 +03:00
.. code-block:: python
import asyncio
from telethon import TelegramClient, events
async def main():
async with TelegramClient(...) as client:
print((await client.get_me()).username)
# ^_____________________^ notice these parenthesis
# You want to ``await`` the call, not the username.
#
message = await client.send_message('me', 'Hi!')
await asyncio.sleep(5)
await message.delete()
@client.on(events.NewMessage(pattern='(?i)hi|hello'))
async def handler(event):
await event.reply('hey')
await client.run_until_disconnected()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
The ``telethon.sync`` magic module simply wraps every method behind:
.. code-block:: python
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
So that you don't have to write it yourself every time. That's the
overhead you pay if you import it, and what you save if you don't.
Learning
2019-05-09 13:24:37 +03:00
========
2018-10-06 21:20:11 +03:00
You know the library uses `asyncio` everywhere, and you want to learn
how to do things right. Even though `asyncio` is its own topic, the
2018-10-06 21:20:11 +03:00
documentation wants you to learn how to use Telethon correctly, and for
that, you need to use `asyncio` correctly too. For this reason, there
2018-10-06 21:20:11 +03:00
is a section called :ref:`mastering-asyncio` that will introduce you to
the `asyncio` world, with links to more resources for learning how to
2018-10-06 21:20:11 +03:00
use it. Feel free to check that section out once you have read the rest.