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

Pyppeteer启动浏览器时阻塞问题求助(Python3.9环境)

Pyppeteer 重复执行时浏览器未关闭导致启动阻塞的优化方案

问题场景

使用Python 3.9编写了基于pyppeteer的循环测试代码,正常运行无问题,但当异常导致浏览器未正常关闭时,下次执行会在browser = await launch处阻塞,无头模式(headless: True)下同样存在该问题。当前想到的临时方案是启动前杀死已存在的pyppeteer进程,现寻求更优解决办法。

原代码如下:

async def pars():
    site_ad = "my_link"
    msg = ''
    new_mass_for_mes = []
    try:
        launcher.defaultArgs().remove("--enable-automation")
        browser = await launch({"headless": False,"userDataDir":"./tool/pyppeteer", "args": ["--no-sandbox", '--disable-setuid-sandbox',"--start-maximized","--disable-infobars","--disable-dev-shm-usage"]})
        page = await browser.newPage()
        await stealth(page)
        await page.goto(site_ad,{'timeout': 15000})
        # ... 省略中间业务逻辑
        await page.waitFor(3000)
        await page.close()
        await browser.close()
    except Exception as e:
        try:
            try:
                await page.close()
            except:
                pass
            try:
                await browser.disconnect()
            except:
                pass
            await browser.close()
        except:
            pass
        logging.error("Error params {0} at {1}".format(site_ad, datetime.datetime.now()))
        logging.error(e)

优化方案

1. 用async with上下文管理器自动管理资源

pyppeteer的Browser和Page对象支持异步上下文管理,能自动在代码块结束(无论正常还是异常)时执行关闭操作,避免手动处理的疏漏。修改后代码更简洁可靠:

async def pars():
    site_ad = "my_link"
    msg = ''
    new_mass_for_mes = []
    try:
        launcher.defaultArgs().remove("--enable-automation")
        # 用async with管理browser,自动关闭
        async with await launch({
            "headless": False,
            "userDataDir": "./tool/pyppeteer", 
            "args": ["--no-sandbox", '--disable-setuid-sandbox',"--start-maximized","--disable-infobars","--disable-dev-shm-usage"]
        }) as browser:
            # 用async with管理page,自动关闭
            async with await browser.newPage() as page:
                await stealth(page)
                await page.goto(site_ad,{'timeout': 15000})
                # ... 省略中间业务逻辑
                await page.waitFor(3000)
    except Exception as e:
        logging.error("Error params {0} at {1}".format(site_ad, datetime.datetime.now()))
        logging.error(e)

这样无需手动调用page.close()和browser.close(),上下文管理器会自动处理,异常时也能保证资源释放。

2. 统一资源清理逻辑,简化异常处理

如果不想用上下文管理器,可以把清理逻辑抽成单独函数,避免嵌套try的混乱,确保每个资源都被正确处理:

async def cleanup(browser, page=None):
    # 先关闭页面
    if page:
        try:
            await page.close()
        except Exception:
            pass
    # 断开并关闭浏览器
    if browser:
        try:
            await browser.disconnect()
        except Exception:
            pass
        try:
            await browser.close()
        except Exception:
            pass

async def pars():
    site_ad = "my_link"
    msg = ''
    new_mass_for_mes = []
    browser = None
    page = None
    try:
        launcher.defaultArgs().remove("--enable-automation")
        browser = await launch({
            "headless": False,
            "userDataDir": "./tool/pyppeteer", 
            "args": ["--no-sandbox", '--disable-setuid-sandbox',"--start-maximized","--disable-infobars","--disable-dev-shm-usage"]
        })
        page = await browser.newPage()
        await stealth(page)
        await page.goto(site_ad,{'timeout': 15000})
        # ... 省略中间业务逻辑
        await page.waitFor(3000)
        await cleanup(browser, page)
    except Exception as e:
        await cleanup(browser, page)
        logging.error("Error params {0} at {1}".format(site_ad, datetime.datetime.now()))
        logging.error(e)

提前初始化browser和page为None,异常时调用统一的清理函数,逻辑更清晰,减少遗漏。

3. 避免固定userDataDir的锁问题

固定userDataDir时,若浏览器进程异常退出,可能残留Chromium的Singleton锁文件,导致新进程启动阻塞。可以改用临时目录作为用户数据目录:

import tempfile

async def pars():
    site_ad = "my_link"
    msg = ''
    new_mass_for_mes = []
    try:
        launcher.defaultArgs().remove("--enable-automation")
        # 创建临时目录作为userDataDir
        with tempfile.TemporaryDirectory() as temp_dir:
            async with await launch({
                "headless": False,
                "userDataDir": temp_dir, 
                "args": ["--no-sandbox", '--disable-setuid-sandbox',"--start-maximized","--disable-infobars","--disable-dev-shm-usage"]
            }) as browser:
                async with await browser.newPage() as page:
                    await stealth(page)
                    await page.goto(site_ad,{'timeout': 15000})
                    # ... 省略中间业务逻辑
                    await page.waitFor(3000)
    except Exception as e:
        logging.error("Error params {0} at {1}".format(site_ad, datetime.datetime.now()))
        logging.error(e)

临时目录会在使用后自动删除,彻底避免残留锁文件导致的阻塞问题。如果需要保留用户数据,可以在启动前检查userDataDir下的锁文件(比如SingletonLock)并删除,但临时目录方案更省心。

内容的提问来源于stack exchange,提问作者The person with the question

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:15:48