Telethon 导致“RuntimeWarning:从未等待协程 'MessageMethods.send_message'”

Telethon leads to `RuntimeWarning: coroutine 'MessageMethods.send_message' was never awaited`

我正在尝试 运行 this first code snippet provided by the Telethon documentation. But, after multiple problems ( and here),我最终得到了这个修改后的版本:

import os
import sys
from telethon.sync import TelegramClient, events

# import nest_asyncio
# nest_asyncio.apply()

session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"


os.chdir(sys.path[0])

if f"{session_name}.session" in os.listdir():
    os.remove(f"{session_name}.session")

async with TelegramClient(session_name, api_id, api_hash) as client:
   client.send_message('me', 'Hello, myself!')
   print(client.download_profile_photo('me'))

   @client.on(events.NewMessage(pattern='(?i).*Hello'))
   async def handler(event):
      await event.reply('Hey!')

   client.run_until_disconnected()

但是现在我收到了这些警告:

usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:23:RuntimeWarning:协程 'MessageMethods.send_message' 从未等待
RuntimeWarning:启用 tracemalloc 以获取对象分配回溯
/usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:24: RuntimeWarning: coroutine 'DownloadMethods.download_profile_photo' was never awaited
RuntimeWarning:启用 tracemalloc 以获取对象分配回溯
/usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:30: Ru​​ntimeWarning: coroutine 'UpdateMethods._run_until_disconnected' was never awaited
RuntimeWarning:启用 tracemalloc 以获取对象分配回溯

当 运行在 Jupyter 上编译代码时。下面是我的问题:

Jupyter 将 运行 asyncio 事件循环,以便您可以在 async def 之外使用 async for / with / await。这与 Telethon 的 .sync 魔法相冲突,在使用 Jupyter、IPython 或类似软件时应尽量避免。

修复您的代码:

from telethon import TelegramClient, events
#            ^ note no .sync

session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"

async with TelegramClient(session_name, api_id, api_hash) as client:
    await client.send_message('me', 'Hello, myself!')
    # ^ note you need to use `await` in Jupyter
    # we are avoiding the `.sync` magic so it needs to be done by yourself

    print(await client.download_profile_photo('me'))
    #     ^ same here, needs await

    @client.on(events.NewMessage(pattern='(?i).*Hello'))
    async def handler(event):
        await event.reply('Hey!')

    await client.run_until_disconnected()
    # ^ once again needs await

如果你想在任何地方 运行 编写代码(Jupyter、Python shell、正常 运行),请务必在 async def 中执行所有操作:

import asyncio

from telethon import TelegramClient, events

session_name = "<session_name>"
api_id = <api_id>
api_hash = "<api_hash>"

async def main():
    async with TelegramClient(session_name, api_id, api_hash) as client:
       await client.send_message('me', 'Hello, myself!')
       print(await client.download_profile_photo('me'))

       @client.on(events.NewMessage(pattern='(?i).*Hello'))
       async def handler(event):
           await event.reply('Hey!')

       await client.run_until_disconnected()

# Only this line changes, the rest will work anywhere.
# Jupyter
await main()

# Otherwise
asyncio.run(main())

只需添加 awaitclient.send_message('me', 'Hello, myself!') 即可解决该错误并在 download_profile_photo 完成其工作后打印 将图像下载到 localhost 这可能就是您不这样做的原因什么都看不到。你应该阅读 telethon documentation thoroughly and also how to use photo downloads correctly

所有对客户端的调用都有延迟,应该始终等待,这样您的代码才不会被阻塞。你应该阅读 asyncio tutorial 正确的代码是:

async with TelegramClient(session_name, api_id, api_hash) as client:
   await client.send_message('me', 'Hello, myself!')
   print(await client.download_profile_photo('me'))

   @client.on(events.NewMessage(pattern='(?i).*Hello'))
   async def handler(event):
      await event.reply('Hey!')

   #await client.run_until_disconnected()

@ 是装饰器,您应该阅读 PEP related to decorators,但简而言之,它们先于您执行函数。

在这种情况下 @client.on(events.NewMessage 表示:

当有新事件恰好是与指定模式匹配的消息时,使用名为 handler

的函数处理它