You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Telethon未接收到新消息时如何定时执行函数且不阻塞消息监听

解决方案

Telethon 基于 asyncio 异步框架运行,只需额外创建独立的定时协程任务,和消息监听逻辑同时挂载到事件循环中即可,两者不会互相阻塞。以下是两种常见场景的实现方案:

场景1:固定每10分钟执行一次,和是否收到消息无关

适合不需要关联消息接收状态,只要到点就执行任务的需求:

import asyncio
from telethon import TelegramClient, events

# 替换为你自己的API参数
api_id = 你的API_ID
api_hash = '你的API_HASH'
client = TelegramClient('session_name', api_id, api_hash)

# 定时执行的自定义函数
async def periodic_task():
    while True:
        # 异步等待10分钟,不会阻塞其他任务
        await asyncio.sleep(10 * 60)
        # 这里编写你需要定时执行的操作
        print("执行10分钟定时任务")

async def main():
    me = await client.get_me()
    print(me.stringify())

    # 启动定时任务,不会阻塞后续的消息监听
    asyncio.create_task(periodic_task())

    # 原有消息监听逻辑
    @client.on(events.NewMessage('TelegramID'))
    async def new_message_listener(event):
        mensaje = event.message.message
        if mensaje is not None:
           print(mensaje)
    
    # 运行客户端直到断开
    await client.run_until_disconnected()

if __name__ == '__main__':
    client.loop.run_until_complete(main())

场景2:连续10分钟未收到消息才执行任务,收到消息重置计时

适合只有在消息空闲时段才触发任务的需求:

import asyncio
import time
from telethon import TelegramClient, events

api_id = 你的API_ID
api_hash = '你的API_HASH'
client = TelegramClient('session_name', api_id, api_hash)

# 记录最后一次收到消息的时间
last_msg_time = time.time()

async def idle_periodic_task():
    global last_msg_time
    while True:
        await asyncio.sleep(60) # 每分钟检查一次空闲状态
        current_time = time.time()
        # 距离上次收到消息超过10分钟则执行操作
        if current_time - last_msg_time >= 10 * 60:
            print("已10分钟未收到消息,执行指定操作")
            # 执行完更新时间,避免每分钟重复触发
            last_msg_time = current_time

async def main():
    global last_msg_time
    me = await client.get_me()
    print(me.stringify())

    asyncio.create_task(idle_periodic_task())

    @client.on(events.NewMessage('TelegramID'))
    async def new_message_listener(event):
        global last_msg_time
        # 收到新消息就更新最后接收时间,重置计时
        last_msg_time = time.time()
        mensaje = event.message.message
        if mensaje is not None:
           print(mensaje)
    
    await client.run_until_disconnected()

if __name__ == '__main__':
    client.loop.run_until_complete(main())

注意事项

  • 所有阻塞操作(比如本地IO、同步网络请求)都要改为异步实现,或者放到线程池中运行,否则会卡住整个asyncio事件循环,导致消息监听和定时任务同时失效
  • 不要使用同步的time.sleep()等待,必须用asyncio.sleep()实现异步等待,才不会阻塞其他任务的运行
  • 如果需要更复杂的定时规则(比如指定时点触发、多任务调度),可以使用APScheduler的异步版本,直接挂载到当前的asyncio事件循环中即可

内容的提问来源于stack exchange,提问作者dyst

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:54:03