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

Telethon与Quart同循环运行时请求失败及数据库锁问题求助

解决方案

核心思路

把Telethon客户端的启动和Quart服务的运行放到同一个异步事件循环中,避免多进程共享数据库文件导致的锁问题,同时保证客户端在请求时处于连接状态。

修改后的完整代码示例

import asyncio
from hypercorn.asyncio import serve
from hypercorn.config import Config
from quart import Quart, Blueprint, render_template
from telethon import TelegramClient, events

# 配置参数(自行替换为你的实际值)
api_id = 123456
api_hash = 'your_api_hash_here'
base_url = '/'
expose_port = 5000

# Telethon client
client = TelegramClient('bot', int(api_id), api_hash)

# Quart app
app = Quart(__name__, template_folder=None, static_folder=None, static_url_path=None)
main = Blueprint('main', __name__, template_folder='templates', static_folder='static', static_url_path='static')

# 监听新消息的事件处理器
@client.on(events.NewMessage(incoming=True))
async def new_chat(event):
    # 处理新消息逻辑
    print(f"收到新消息: {event.message.text}")

# Quart路由:获取频道列表
@main.route('/new', methods=['GET', 'POST'])
async def new():
    channels = []
    # 直接使用已连接的客户端遍历对话
    async for dialog in client.iter_dialogs():
        channels.append((dialog.id, dialog.name))
    
    return await render_template(
        'new_channel.html',
        channels=channels
    )

async def startup():
    # 启动Telethon客户端
    await client.start()
    # 确保客户端一直运行(不会阻塞,因为是异步的)
    asyncio.create_task(client.run_until_disconnected())

async def start(conf):
    app.register_blueprint(main, url_prefix=base_url)
    # 在启动Quart服务前先启动Telethon
    await startup()
    await serve(app, conf)

if __name__ == '__main__':
    config = Config()
    config.bind = "127.0.0.1:" + str(expose_port)
    
    # 运行主异步函数
    asyncio.run(start(config))

关键修改点说明

  1. 移除ProcessPoolExecutor:不再用多进程隔离Telethon,因为Telethon本身是异步的,和Quart可以共存于同一个事件循环。
  2. 异步启动Telethon:在startup函数中用await client.start()启动客户端,然后用asyncio.create_task把client.run_until_disconnected()作为后台任务运行,不会阻塞Quart服务。
  3. 统一事件循环:所有异步操作(Telethon消息监听、Quart请求处理)都在同一个asyncio.run()启动的事件循环里执行,保证客户端在请求时处于已连接状态。
  4. 避免数据库锁:只有一个进程操作Telethon的SQLite会话文件,彻底解决sqlite3.OperationalError: database is locked问题。

额外注意事项

  • 如果你的消息处理逻辑有耗时操作(比如IO密集或CPU密集任务),不要直接在new_chat里同步执行,应该用asyncio.create_task或者线程池(loop.run_in_executor)异步处理,避免阻塞事件循环。
  • 确保Telethon的会话文件(bot.session)所在目录有读写权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:55:28