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

Telegram Bot异步定时通知线程报错问题求助

解决Telegram Bot定时通知的线程与异步兼容问题

问题描述

开发Telegram Bot时,需按user_id定期发送通知。启动数据检查循环后代码冻结,无法处理用户后续请求;尝试用线程运行函数,出现报错且无法发送消息。

报错信息

Exception in thread Thread-2:
Task exception was never retrieved
future: <Task finished name='Task-14' coro=<Dispatcher._process_polling_updates() done, defined at /usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/dispatcher.py:407> exception=TypeError("object NoneType can't be used in 'await' expression")>
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/dispatcher.py", line 415, in _process_polling_updates
    for responses in itertools.chain.from_iterable(await self.process_updates(updates, fast)):
  File "/usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/dispatcher.py", line 235, in process_updates
    return await asyncio.gather(*tasks)
  File "/usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/handler.py", line 117, in notify
    response = await handler_obj.handler(*args, **partial_data)
  File "/usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/dispatcher.py", line 256, in process_update
    return await self.message_handlers.notify(update.message)
  File "/usr/local/lib/python3.9/dist-packages/aiogram/dispatcher/handler.py", line 117, in notify
    response = await handler_obj.handler(*args, **partial_data)
  File "/root/home/vtk/./botvtk.py", line 34, in online
    await threading.Thread(target=service.run(user_id), daemon=True, name=None).start()
TypeError: object NoneType can't be used in 'await' expression
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
TypeError: 'coroutine' object is not callable

相关代码

bot.py

import requests
import json
import telebot
import buttonbot
import time
from telebot import types
from aiogram import Bot, Dispatcher, executor, types
from aiogram.dispatcher.filters import Text
import service
import threading
import bottoken

bot = Bot(token=bottoken)

notext = 'notext'

dp = Dispatcher(bot)

@dp.message_handler(commands=['help'])
async def online(message: types.Message):
    await bot.send_message(message.from_user.id, f"ваш id: {message.from_user.id}")
    user_id = message.from_user.id
    await threading.Thread(target=service.run(user_id), daemon=True, name=None).start()

service.py

import requests
import json
import time
import threading
from data import data
from headers import headers
from aiogram import executor
import sched, time


notext = 'notext'

rt = ''

method = f"https://api.telegram.org/bot{rt}/sendMessage"

async def get_updates(file_count=0):
    url = ""
    url4 = ""
    session = requests.Session()
    session.headers.update(headers)
    response =  session.post(url, data=data)
    result = session.get(url4, data=data).json()
    return result['rows']

async def run(user_id):
    url = ""
    url2 = ""
    url3 = ""
    url4 = ""
    session = requests.Session()
    session.headers.update(headers)
    response =  session.post(url, data=data)
    update_id = get_updates()[-1]['id']
    for _ in range(5):
       messages = get_updates(update_id)
        for message in messages:
            if update_id < message['id']:
                update_id = message['id']
                card = (f"New: {message['number']}")
                r = requests.post(method, data={
                    "chat_id": user_id,
                    "text": card
                    })
                time.sleep(60)

解决方案

核心问题分析

  1. 线程与异步函数不兼容:service.run是异步函数,直接传给threading.Thread的target会把协程对象当作普通函数调用,触发TypeError: 'coroutine' object is not callable。
  2. 错误使用await:threading.Thread.start()是同步方法,不需要await,加上await会尝试等待None(start()返回None),导致TypeError: object NoneType can't be used in 'await' expression。
  3. 同步阻塞问题:service.run中的time.sleep(60)是同步阻塞操作,会卡住线程;requests是同步HTTP库,也会阻塞异步环境。

修复步骤

1. 用asyncio后台任务替代线程

aiogram基于asyncio,直接用asyncio的后台任务管理定时任务更适配,无需手动使用threading。

修改bot.py的online函数:

import asyncio  # 导入asyncio

@dp.message_handler(commands=['help'])
async def online(message: types.Message):
    await bot.send_message(message.from_user.id, f"ваш id: {message.from_user.id}")
    user_id = message.from_user.id
    # 创建后台任务,无需await start()
    asyncio.create_task(service.run(user_id, bot))  # 将bot实例传入run函数

2. 改造service.py为全异步模式

  • 替换requests为异步HTTP库aiohttp
  • 把time.sleep换成asyncio.sleep
  • 修复异步函数调用时的await缺失(原代码get_updates()未加await)
  • 用传入的bot实例发送消息,无需手动拼接API请求

修改后的service.py:

import asyncio
import aiohttp  # 导入aiohttp
from data import data
from headers import headers

async def get_updates(session):
    url = ""
    url4 = ""
    await session.post(url, data=data)  # 异步POST请求
    async with session.get(url4, data=data) as resp:  # 异步GET请求
        result = await resp.json()
        return result['rows']

async def run(user_id, bot):
    url = ""
    async with aiohttp.ClientSession(headers=headers) as session:  # 创建异步Session
        await session.post(url, data=data)
        updates = await get_updates(session)
        update_id = updates[-1]['id']
        for _ in range(5):
            messages = await get_updates(session)
            for message in messages:
                if update_id < message['id']:
                    update_id = message['id']
                    card = f"New: {message['number']}"
                    await bot.send_message(user_id, card)  # 用bot实例发送消息
                    await asyncio.sleep(60)  # 异步sleep,不阻塞事件循环

3. 其他注意事项

  • 确保bottoken中的token正确,service.py无需再单独设置rt,直接使用传入的bot实例即可。
  • 若需长期运行的定时任务,可结合asyncio.create_task与无限循环(需添加适当sleep),或使用第三方库如apscheduler的异步版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 00:55:33