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

在Python类中使用asyncio和aiohttp遇到的问题

这种情况我之前踩过坑!大概率是你在类里处理异步逻辑的姿势不对——函数式写法时你可能直接用asyncio.run()把协程跑起来了,但放到类里后,要么是没正确触发异步方法执行,要么是事件循环的管理出了问题,导致程序卡在那儿没推进。下面给你拆解常见问题和解决办法:

常见问题&修复方案

1. 用同步方式直接调用异步方法

这是最容易犯的错误:在类的同步方法里直接调用self.xxx_async(),这只会返回一个协程对象,根本没真正执行。比如:

# 错误示例
class AsyncScraper:
    async def fetch_page(self):
        async with aiohttp.ClientSession() as session:
            return await session.get("https://example.com")

    def start(self):
        # 这里只是创建了协程,没有调度执行
        self.fetch_page()

修复方式:要么在同步方法里用asyncio.run()包裹异步调用,要么把整个启动逻辑改成异步:

# 方案1:同步启动
def start(self):
    asyncio.run(self.fetch_page())

# 方案2:异步启动(更推荐,适合复杂场景)
async def start_async(self):
    await self.fetch_page()

# 然后在Main.py里这样调用
asyncio.run(scraper.start_async())

2. 类内部事件循环管理混乱

如果你的类自己维护了事件循环(比如在__init__里创建loop = asyncio.get_event_loop()),但Main.py里又用asyncio.run()启动了新循环,就会导致协程被挂在未运行的循环里,程序直接锁死。

修复方式:统一让顶层的asyncio.run()管理事件循环,类里的所有异步方法只负责定义逻辑,用await调用即可,不要自己创建/管理循环。

3. aiohttp ClientSession未正确管理

如果把ClientSession作为类的实例属性,但没在退出时关闭,可能导致资源泄漏,进而让程序卡住。比如:

# 有隐患的写法
class AsyncScraper:
    def __init__(self):
        self.session = aiohttp.ClientSession()  # __init__是同步方法,这里创建异步对象有风险

    async def fetch(self, url):
        return await self.session.get(url)

修复方式:用异步方法初始化Session,并且在使用完后关闭:

class AsyncScraper:
    def __init__(self):
        self.session = None

    async def init_session(self):
        self.session = aiohttp.ClientSession()

    async def fetch(self, url):
        if not self.session:
            await self.init_session()
        return await self.session.get(url)

    async def cleanup(self):
        if self.session:
            await self.session.close()

# Main.py里的调用逻辑
async def main():
    scraper = AsyncScraper()
    try:
        resp = await scraper.fetch("https://example.com")
        print(await resp.text())
    finally:
        await scraper.cleanup()

asyncio.run(main())

4. 异步方法里混入同步阻塞代码

如果你的类方法里不小心用了time.sleep()、requests.get()这类同步阻塞操作,会直接把整个事件循环卡死,看起来就像程序无响应。

修复方式:把所有阻塞操作换成异步版本——比如用asyncio.sleep()替代time.sleep(),用aiohttp替代requests。

完整可运行示例
# AsyncFetcher.py
import asyncio
import aiohttp

class AsyncFetcher:
    def __init__(self):
        self._session = None

    async def _setup(self):
        # 异步初始化资源
        if not self._session:
            self._session = aiohttp.ClientSession()

    async def fetch_json(self, url):
        await self._setup()
        async with self._session.get(url) as resp:
            resp.raise_for_status()
            return await resp.json()

    async def close(self):
        # 清理资源
        if self._session:
            await self._session.close()

# Main.py
from AsyncFetcher import AsyncFetcher

async def main():
    fetcher = AsyncFetcher()
    try:
        todo = await fetcher.fetch_json("https://jsonplaceholder.typicode.com/todos/1")
        print(f"Fetched todo: {todo}")
    finally:
        await fetcher.close()

if __name__ == "__main__":
    asyncio.run(main())

如果还是排查不出问题,可以开启异步调试模式:asyncio.run(main(), debug=True),这样能看到协程的调度状态,更容易找到卡住的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:56:51