python 中的异步错误

Async Errors in python

我正在编写电报用户机器人(带有 telethon),它每 60 秒向一些聊天发送一条消息。

我正在使用 2 个线程,但出现以下错误:“RuntimeWarning:从未等待协程 'sender'”和“no 运行 事件循环".

我的代码:

....

async def sender():
    for chat in chats :
        try:
            if  chat.megagroup == True:
                await client.send_message(chat, messaggio)
        except:
            await client.send_message(myID, 'error')
schedule.every(60).seconds.do(asyncio.create_task(sender()))

...
class checker1(Thread):
    def run(self):
        while True:
            schedule.run_pending()
            time.sleep(1)
class checker2(Thread):
    def run(self):
        while True:
            client.add_event_handler(handler)
            client.run_until_disconnected()
checker2().start()
checker1().start()

我搜索了解决方案,但没有找到任何东西...

您的代码存在一些问题。 asyncio 抱怨“没有 运行ning 事件循环”,因为您的程序永远不会在任何地方启动事件循环,并且没有事件循环 运行ning 就无法安排任务。参见 Asyncio in corroutine RuntimeError: no running event loop。为了启动事件循环,如果你的程序有一个主协程,你可以使用 asyncio.run_until_complete(),或者你可以使用 asyncio.get_event_loop().run_forever() 到 运行 永远的事件循环。

第二个问题是schedule.every(60).seconds.do()的错误用法,这被第一个错误所掩盖。 schedule 期望传入一个 函数 ,而不是一个可等待对象(这就是 asyncio.create_task(sender()) returns)。这通常会导致 TypeError,但没有 运行ning 事件循环的 create_task() 首先引发异常,因此从未引发此异常。您需要定义一个函数,然后将其传递给 schedule,如下所示:

def start_sender():
    asyncio.create_task(sender())
schedule.every(60).seconds.do(start_sender)

只要事件循环在程序的其他地方启动,这就应该有效。

除非您知道自己在做什么,否则您应该避免将线程与 asyncio 一起使用。可以使用 asyncio 重写代码,如下所示,因为大多数时候您实际上并不需要线程:

import asyncio

async def sender():
    for chat in chats :
        try:
            if  chat.megagroup == True:
                await client.send_message(chat, messaggio)
        except:
            await client.send_message(myID, 'error')

async def checker1():
    while True:
        await sender()
        await asyncio.sleep(60)  # every 60s

async def main():
    await asyncio.create_task(checker1())  # background task
    await client.run_until_disconnected() 

client.loop.run_until_complete(main())

此代码并不完美(您应该适当取消并在程序结束时等待 checker1),但它应该可以工作。

附带说明一下,您不需要 client.run_until_disconnected()。该调用只是阻塞(运行)直到客户端断开连接。如果你能保持程序 运行 不同,只要 asyncio 运行,client 就会工作。

另一件事:裸 except: 是一个非常糟糕的主意,并且可能会导致异常问题。至少,换成except Exception.