基于Threads、asyncio的多账号并发轮询代码运行问题排查
多账号并发检测消息实现方案
原代码无法运行的核心原因
- 你写的
startChecking是同步阻塞函数,内部的while True是无限循环,for循环执行到第一个账号时就会卡在死循环里,永远不会启动后续账号的检测流程 - asyncio使用逻辑错误:
run_until_complete会阻塞等待传入的任务执行完成才会往下走,你传入的是无限循环任务,自然永远卡在第一个账号;另外你写的startChecking本身是同步函数,根本不能被事件循环调度,就算加了await也还是阻塞运行 - 每个账号单独新建事件循环的写法本身就无法实现任务并发,不同循环里的任务没法同时调度
补充:你原有代码里
if lastData == lastChat分支下的gg = 0是无意义的冗余代码,没有实际作用,可以直接删除。
方案1:多线程实现(改造成本最低,推荐新手用)
对你现有的同步代码改动极小,不需要重构原有请求逻辑,每个账号分配一个独立线程维护自己的会话,线程之间互不干扰,10个账号以内的场景用这个方案完全够用。
完整实现代码:
import time import threading # 你原有的检测逻辑完全不需要改动 def startChecking(login, password): session = startSession() logIn(session, login, password) while True: lastData = findAll(session) time.sleep(5) lastChat = findAll(session) if lastData != lastChat: print(f'{login}', lastChat['userSms']) if __name__ == '__main__': allAcc = list(collectionFunPay.find()) thread_list = [] for acc in allAcc: login = acc['login'] password = acc['password'] print(f"启动账号检测任务:{login}") # 为每个账号创建独立守护线程 t = threading.Thread( target=startChecking, args=(login, password), daemon=True ) t.start() thread_list.append(t) # 阻塞主线程,防止程序直接退出 for t in thread_list: t.join()
方案注意点:
- 每个线程内部独立创建session,不同账号的会话完全隔离,不会出现串号问题
- 守护线程会随主线程一起退出,不需要额外写退出逻辑,不会残留僵尸进程
方案2:异步协程实现(适合账号量大的场景)
如果需要同时跑几十个甚至上百个账号,多线程的上下文切换开销会明显升高,这时候用异步协程方案资源占用更低,调度效率更高。
注意:这个方案需要你把原有同步的网络请求、等待逻辑全部替换成异步版本,否则会阻塞整个事件循环。
完整实现代码:
import asyncio # 注意:startSession、logIn、findAll都要替换成对应的异步实现,比如用aiohttp替代requests发请求 async def startChecking(login, password): session = await async_startSession() await async_logIn(session, login, password) while True: lastData = await async_findAll(session) await asyncio.sleep(5) # 这里必须用asyncio.sleep,不能用time.sleep,否则会卡住所有账号的检测 lastChat = await async_findAll(session) if lastData != lastChat: print(f'{login}', lastChat['userSms']) if __name__ == '__main__': allAcc = list(collectionFunPay.find()) async def main(): # 为所有账号创建并发任务 tasks = [] for acc in allAcc: tasks.append(asyncio.create_task(startChecking(acc['login'], acc['password']))) # 并发运行所有检测任务 await asyncio.gather(*tasks) asyncio.run(main())
方案注意点:
- 异步逻辑里绝对不能混用同步阻塞方法,否则整个事件循环会被卡住,所有账号的检测都会暂停
- 所有账号的检测任务在同一个事件循环里调度,内存和CPU开销远低于多线程方案
内容的提问来源于stack exchange,提问作者Влад Даниленко
相关产品推荐
相关产品推荐

