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
.
我正在编写电报用户机器人(带有 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
.