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

Python多进程+sync_playwright报错:Target page, context or browser has been closed

问题排查:Playwright TargetClosedError异常分析

问题现象

  • DispatcherService类从Mongo获取Cookie后启动Playwright Chromium,调用verify_status方法时self.browser.new_page()可正常运行,但调用init_scraper方法时执行同一代码抛出Target page, context or browser has been closed异常
  • 复用verify_status的页面可正常工作,但业务需求必须创建新页面
  • 将prepare_browser放入类__init__仍报错
  • main方法启动两个进程,其中execute_all_dispatcher进程会导致浏览器上下文失效

相关代码

main.py

if __name__ == "__main__":
    node = WorkerNodeService()
    node.init() # Works fine. Just random class
    q1 = Queue()
    q2 = Queue()
    p1 = Process(target=execute_all_redis, args=(q1, q2,)) # Works fine. A redis consumer class
    p1.start()
    p2 = Process(target=execute_all_dispatcher, args=(q1, q2,)) # Browser context dies
    p2.start()

DispatcherService.py

from Playwright.packages.utils.Logger import Logger
from Playwright.packages.multiprocess.FacebookProcess import FacebookProcess
from Playwright.packages.service.CookiesFacebookService import CookiesFacebookService


class DispatcherService:
    def __init__(self):
        self.logger = Logger()
        self.log = self.logger.getLogger(self.__class__.__name__)
        self.instances_service = CookiesFacebookService()
        self.list_of_processes = []

    def init(self):
        node = os.environ.get("NODE", "node")
        for i in self.instances_service.find_by_node(node):
            self.build_worker_process(i)

    def build_worker_process(self, instance):
        fb_process_object = FacebookProcess(instance)
        self.list_of_processes.append(fb_process_object)
        fb_process_object.run()


def execute_all_dispatcher(q1, q2):
    ds = DispatcherService()
    ds.init()

FacebookProcess.py

from Playwright.packages.utils.Logger import Logger
from Playwright.packages.service.FacebookService import FacebookService


class FacebookProcess:
    def __init__(self, instance):
        self.facebook_service = FacebookService(instance)
        self.instance = instance # Dict
        self.to_run = False
        self.logger = Logger()
        self.log = self.logger.getLogger(self.__class__.__name__)

    def run(self):
        if not self.to_run:
            self.to_run = True
            self.facebook_service.prepare_browser()
        while self.to_run:
            if not self.facebook_service.verify_status():
                self.log.error("Error.")
            time.sleep(3)
            self.facebook_service.init_scraper()
            time.sleep(3600)

FacebookService.py

import os
import sys
import time
import base64
import traceback
from playwright.sync_api import sync_playwright
from Playwright.packages.utils.Logger import Logger
from Playwright.packages.utils.BrowserParams import options
from Playwright.playwrightbrowser.PlaywrightScraper import PlaywrightScraper


class FacebookService:
    def __init__(self, instance):
        self.playwright = None
        self.browser = None
        self.instance = instance # Dict
        self.cookie = instance["reqCookies"]
        self.logger = Logger()
        self.options = options
        self.log = self.logger.getLogger(self.__class__.__name__)

    def prepare_browser(self):
        try:
            self.playwright = sync_playwright().start()
            self.browser = self.playwright.chromium.launch(**self.options)
        except Exception as ex0:
            try:
                self.log.error(f"Error launching Playwright: {repr(ex0)}. Retrying...", traceback.format_exc())
                time.sleep(8)
                self.playwright = sync_playwright().start()
                self.browser = self.playwright.chromium.launch(**self.options)
            except Exception as ex1:
                self.log.error(f"Error launching Playwright: {repr(ex1)}. Finishing execution.", traceback.format_exc())
                sys.exit()

    def init_scraper(self):
        # page = self.browser.contexts[0].pages[0]  # Works fine, but need new page, not the same
        page = self.browser.new_page() # CONTEXT OR BROWSER DESTROYED BY SOME REASON
        page.context.add_cookies(self.cookie)
        PlaywrightScraper(page).launch_playwright()
        self.stop_browser()

    def verify_status(self):
        page = self.browser.new_page() # Works fine
        page.context.add_cookies(self.cookie)
        page.goto("https://www.facebook.com")
        if ("checkpoint" not in page.url) and not (
                page.is_visible("//div/h1[contains(text(), \"Connect with people who share your interests.\")]")):
            self.log.info(f"Instance: OK")
            page.close()
            return True
        else:
            self.log.info(f"Instance: FAIL. Check instance.")
            page.close()
            return False

    def make_screenshots(self):
        page = self.browser.new_page()
        page.context.add_cookies(self.cookie)
        page.screenshot(path="ss.jpg")
        with open("ss.jpg", "rb") as image_file:
            converted = base64.b64encode(image_file.read())
        page.close()

    def stop_browser(self):
        self.log.info(f"Shutting down instance: {node}")
        try:
            self.browser.close()
            self.playwright.stop()
        except Exception:
            self.log.error("Error trying to close and quit Playwright. Retrying")
            self.browser.close()
            self.playwright.stop()

PlaywrightScraper.py

class PlaywrightScraper:
    def __init__(self, page):
        self.page = page
        self.logger = Logger()
        self.log = self.logger.getLogger(self.__class__.__name__)

    def launch_playwright(self):
        page = self.page
        page.goto("https://www.facebook.com", wait_until='load')
        ...

错误日志

--- Logging error ---
Traceback (most recent call last):
  File "/mnt/c/Users/Personal/PycharmProjects/playwright/Playwright/packages/service/FacebookService.py", line 46, in init_scraper
    page = self.browser.new_page()
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/sync_api/_generated.py", line 14584, in new_page
    self._sync(
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_sync_base.py", line 115, in _sync
    return task.result()
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_browser.py", line 178, in new_page
    return await self._connection.wrap_api_call(inner)
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_connection.py", line 495, in wrap_api_call
    return await cb()
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_browser.py", line 172, in inner
    context = await self.new_context(**params)
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_browser.py", line 127, in new_context
    channel = await self._channel.send("newContext", params)
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_connection.py", line 63, in send
    return await self._connection.wrap_api_call(
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_connection.py", line 490, in wrap_api_call
    return await cb()
  File "/home/user/.virtualenvs/playwright/lib/python3.10/site-packages/playwright/_impl/_connection.py", line 101, in inner_send
    result = next(iter(done)).result()
playwright._impl._errors.TargetClosedError: Target page, context or browser has been closed

环境版本

Python 3.10.12 
Ubuntu 22.04.3 LTS on WSL2
playwright 1.41.1
chromium latest version

问题原因分析

  1. 进程间资源冲突:execute_all_dispatcher作为独立进程启动,Playwright的浏览器实例与进程强绑定,无法跨进程共享。当前代码在子进程中创建浏览器,但存在资源被其他进程意外释放的风险。
  2. 浏览器生命周期与循环不匹配:init_scraper方法最后调用self.stop_browser()关闭了浏览器和Playwright实例,但run方法的循环仍会继续执行,后续循环调用方法时self.browser已处于关闭状态,触发异常。
  3. 上下文管理混乱:每次调用new_page都会创建新上下文,未统一管理上下文生命周期,容易引发资源泄漏或意外销毁。

解决方案

  1. 为每个浏览器实例分配独立进程:修改DispatcherService的build_worker_process方法,让每个FacebookProcess在单独子进程中运行,避免进程间资源冲突:
def build_worker_process(self, instance):
    from multiprocessing import Process
    p = Process(target=FacebookProcess(instance).run)
    p.start()
    self.list_of_processes.append(p)
  1. 修复循环中的浏览器初始化逻辑:在run方法的循环中,每次执行init_scraper后浏览器会被关闭,因此需要在下次循环前重新初始化浏览器:
def run(self):
    self.to_run = True
    while self.to_run:
        self.facebook_service.prepare_browser()
        if not self.facebook_service.verify_status():
            self.log.error("Error.")
        time.sleep(3)
        self.facebook_service.init_scraper()
        time.sleep(3600)
  1. 统一上下文管理:在prepare_browser中创建持久化上下文,一次性添加Cookie,后续页面都基于该上下文创建,减少资源开销:
def prepare_browser(self):
    try:
        self.playwright = sync_playwright().start()
        self.browser = self.playwright.chromium.launch(**self.options)
        self.context = self.browser.new_context()
        self.context.add_cookies(self.cookie)
    except Exception as ex0:
        try:
            self.log.error(f"Error launching Playwright: {repr(ex0)}. Retrying...", traceback.format_exc())
            time.sleep(8)
            self.playwright = sync_playwright().start()
            self.browser = self.playwright.chromium.launch(**self.options)
            self.context = self.browser.new_context()
            self.context.add_cookies(self.cookie)
        except Exception as ex1:
            self.log.error(f"Error launching Playwright: {repr(ex1)}. Finishing execution.", traceback.format_exc())
            sys.exit()

修改verify_status和init_scraper方法:

def verify_status(self):
    page = self.context.new_page()
    page.goto("https://www.facebook.com")
    if ("checkpoint" not in page.url) and not (
            page.is_visible("//div/h1[contains(text(), \"Connect with people who share your interests.\")]")):
        self.log.info(f"Instance: OK")
        page.close()
        return True
    else:
        self.log.info(f"Instance: FAIL. Check instance.")
        page.close()
        return False

def init_scraper(self):
    page = self.context.new_page()
    PlaywrightScraper(page).launch_playwright()
    page.close()
    self.stop_browser()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:10:55