PyInstaller编译后Playwright调用Edge持久化上下文遇TargetClosedError
PyInstaller编译后Playwright启动Edge持久化上下文抛出TargetClosedError
PyInstaller编译Python脚本后,生成的可执行文件无法通过Playwright启动Microsoft Edge的持久化浏览器上下文,抛出TargetClosedError异常。相同代码在虚拟环境中作为普通Python脚本运行完全正常。问题几乎持续出现,但调试时(添加消息框、暂停等操作)偶尔能成功,推测存在竞态条件。
此前使用executable_path和launch_persistent_context的方式可正常工作(最后一次成功是2025年2月,编译版本为2024年4月),环境未做重大变更,但Microsoft Edge可能已更新,且本次在新电脑上编译(Python版本同为3.12)。已通过connect_over_cdp实现功能并验证稳定性,现希望恢复使用持久化上下文与executable_path的方式。
最小可复现示例(test.py)
import os import asyncio from playwright.async_api import async_playwright async def main(): executable_path = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" base_dir = os.getcwd() user_data_dir = os.path.join(base_dir, "User Data") os.makedirs(user_data_dir, exist_ok=True) async with async_playwright() as p: context = await p.chromium.launch_persistent_context( user_data_dir=user_data_dir, headless=False, executable_path=executable_path, ) page = await context.new_page() await page.goto("https://google.com") # Wait a few seconds to observe the browser window await asyncio.sleep(5) print("Page title:", await page.title()) await context.close() if __name__ == "__main__": asyncio.run(main())
编译后运行时回溯信息
Traceback (most recent call last): File "test.py", line 24, in <module> File "asyncio\runners.py", line 194, in run File "asyncio\runners.py", line 118, in run File "asyncio\base_events.py", line 686, in run_until_complete File "test.py", line 11, in main File "playwright\async_api\_generated.py", line 14681, in launch_persistent_context File "playwright\_impl\_browser_type.py", line 159, in launch_persistent_context File "playwright\_impl\_connection.py", line 61, in send File "playwright\_impl\_connection.py", line 528, in wrap_api_call playwright._impl._errors.TargetClosedError: BrowserType.launch_persistent_context: Target page, context or browser has been closed Browser logs: <launching> C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe --disable-field-trial-config --disable-background-networking --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding,ThirdPartyStoragePartitioning,LensOverlay,PlzDedicatedWorker --allow-pre-commit-input --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --no-service-autorun --export-tagged-pdf --disable-search-engine-choice-screen --unsafely-disable-devtools-self-xss-warnings --no-sandbox --user-data-dir=C:\Users\[username]\Desktop\Playwright_Test\dist\test\User Data --remote-debugging-pipe about:blank <launched> pid=21472 [pid=21472] <process did exit: exitCode=0, signal=null> [pid=21472] starting temporary directories cleanup Call log: - <launching> C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe --disable-field-trial-config --disable-background-networking --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding,ThirdPartyStoragePartitioning,LensOverlay,PlzDedicatedWorker --allow-pre-commit-input --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --no-service-autorun --export-tagged-pdf --disable-search-engine-choice-screen --unsafely-disable-devtools-self-xss-warnings --no-sandbox --user-data-dir=C:\Users\[username]\Desktop\Playwright_Test\dist\test\User Data --remote-debugging-pipe about:blank - - <launched> pid=21472 - - [pid=21472] <process did exit: exitCode=0, signal=null> - - [pid=21472] starting temporary directories cleanup
编译脚本(build.bat)
call venv\scripts\activate set PLAYWRIGHT_BROWSERS_PATH=0 pyinstaller --noconsole test.py
编译输出
207 INFO: PyInstaller: 6.11.1, contrib hooks: 2024.11 207 INFO: Python: 3.12.8 242 INFO: Platform: Windows-11-10.0.22631-SP0 242 INFO: Python environment: C:\Program Files\Python312 244 INFO: wrote C:\Users\[username]\Desktop\Playwright_Test\test.spec 247 INFO: Module search paths (PYTHONPATH): ['C:\\Program Files\\Python312\\Scripts\\pyinstaller.exe', 'C:\\Program Files\\Python312\\python312.zip', 'C:\\Program Files\\Python312\\DLLs', 'C:\\Program Files\\Python312\\Lib', 'C:\\Program Files\\Python312', 'C:\\Users\\[username]\\AppData\\Roaming\\Python\\Python312\\site-packages', 'C:\\Program Files\\Python312\\Lib\\site-packages', 'C:\\Program Files\\Python312\\Lib\\site-packages\\win32', 'C:\\Program Files\\Python312\\Lib\\site-packages\\win32\\lib', 'C:\\Program Files\\Python312\\Lib\\site-packages\\Pythonwin', 'C:\\Program Files\\Python312\\Lib\\site-packages\\setuptools\\_vendor', 'C:\\Users\\[username]\\Desktop\\Playwright_Test'] 717 INFO: checking Analysis 739 INFO: Building because inputs changed 739 INFO: Running Analysis Analysis-00.toc 739 INFO: Target bytecode optimization level: 0 739 INFO: Initializing module dependency graph... 742 INFO: Initializing module graph hook caches... 749 INFO: Analyzing base_library.zip ... 2152 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 3239 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 3710 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 3921 INFO: Caching module dependency graph... 3987 INFO: Looking for Python shared library... 3997 INFO: Using Python shared library: C:\Program Files\Python312\python312.dll 3997 INFO: Analyzing C:\Users\[username]\Desktop\Playwright_Test\test.py 4085 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 4166 INFO: Processing standard module hook 'hook-xml.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 4496 INFO: Processing standard module hook 'hook-playwright.async_api.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\playwright\\_impl\\__pyinstaller' 4859 INFO: Processing standard module hook 'hook-platform.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks' 5025 INFO: Processing module hooks (post-graph stage)... 5143 INFO: Performing binary vs. data reclassification (343 entries) 5219 INFO: Looking for ctypes DLLs 5225 INFO: Analyzing run-time hooks ... 5228 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks' 5231 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks' 5231 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from 'C:\\Program Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks' 5239 INFO: Looking for dynamic libraries 5465 INFO: Extra DLL search directories (AddDllDirectory): [] 5471 INFO: Extra DLL search directories (PATH): [] 5714 INFO: Warnings written to C:\Users\[username]\Desktop\Playwright_Test\build\test\warn-test.txt 5729 INFO: Graph cross-reference written to C:\Users\[username]\Desktop\Playwright_Test\build\test\xref-test.html 5753 INFO: checking PYZ 5774 INFO: Building because name changed 5774 INFO: Building PYZ (ZlibArchive) C:\Users\[username]\Desktop\Playwright_Test\build\test\PYZ-00.pyz 6099 INFO: Building PYZ (ZlibArchive) C:\Users\[username]\Desktop\Playwright_Test\build\test\PYZ-00.pyz completed successfully. 6105 INFO: checking PKG 6114 INFO: Building because name changed 6114 INFO: Building PKG (CArchive) test.pkg 6132 INFO: Building PKG (CArchive) test.pkg completed successfully. 6136 INFO: Bootloader C:\Program Files\Python312\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\runw.exe 6136 INFO: checking EXE 6175 INFO: Building because name changed 6179 INFO: Building EXE from EXE-00.toc 6179 INFO: Copying bootloader EXE to C:\Users\[username]\Desktop\Playwright_Test\build\test\test.exe 6325 WARNING: Execution of 'remove_all_resources' failed on attempt #1 / 20: error(110, 'EndUpdateResourceW', 'The system cannot open the device or file specified.'). Retrying in 0.05 second(s)... 6380 INFO: Copying icon to EXE 6397 INFO: Copying 0 resources to EXE 6397 INFO: Embedding manifest in EXE 6538 INFO: Appending PKG archive to EXE 6541 WARNING: Execution of '_append_data_to_exe' failed on attempt #1 / 20: PermissionError(13, 'Permission denied'). Retrying in 0.05 second(s)... 6597 WARNING: Execution of '_append_data_to_exe' failed on attempt #2 / 20: PermissionError(13, 'Permission denied'). Retrying in 0.06 second(s)... 6654 WARNING: Execution of '_append_data_to_exe' failed on attempt #3 / 20: PermissionError(13, 'Permission denied'). Retrying in 0.06 second(s)... 6714 WARNING: Execution of '_append_data_to_exe' failed on attempt #4 / 20: PermissionError(13, 'Permission denied'). Retrying in 0.06 second(s)... 6954 INFO: Fixing EXE headers 7658 INFO: Building EXE from EXE-00.toc completed successfully. 7661 INFO: checking COLLECT WARNING: The output directory "C:\Users\[username]\Desktop\Playwright_Test\dist\test" and ALL ITS CONTENTS will be REMOVED! Continue? (y/N)y On your own risk, you can use the option `--noconfirm` to get rid of this question. 10946 INFO: Removing dir C:\Users\[username]\Desktop\Playwright_Test\dist\test 11021 INFO: Building COLLECT COLLECT-00.toc 11682 INFO: Building COLLECT COLLECT-00.toc completed successfully.
依赖清单(requirements.txt)
et_xmlfile==2.0.0 greenlet==3.1.1 numpy==2.2.1 openpyxl==3.1.5 pandas==2.2.3 playwright==1.49.1 pyee==12.0.0 PySide6==6.8.1.1 PySide6_Addons==6.8.1.1 PySide6_Essentials==6.8.1.1 python-dateutil==2.9.0.post0 pytz==2024.2 shiboken6==6.8.1.1 six==1.17.0 typing_extensions==4.12.2 tzdata==2024.2
可能的解决方案
1. 开启控制台输出调试
去掉编译脚本中的--noconsole参数,让可执行文件显示控制台窗口,观察Edge启动时的实时日志,排查隐藏的启动失败原因:
pyinstaller test.py
2. 添加初始化延迟缓解竞态条件
在启动Playwright上下文前添加短暂延迟,模拟调试时的暂停效果,验证是否为进程启动时序问题:
async def main(): executable_path = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" base_dir = os.getcwd() user_data_dir = os.path.join(base_dir, "User Data") os.makedirs(user_data_dir, exist_ok=True) # 添加2秒延迟 await asyncio.sleep(2) async with async_playwright() as p: context = await p.chromium.launch_persistent_context( user_data_dir=user_data_dir, headless=False, executable_path=executable_path, ) # 后续代码不变
3. 改用TCP端口进行调试通信
替换默认的管道通信为TCP端口,可能解决编译后进程间通信的竞态问题:
context = await p.chromium.launch_persistent_context( user_data_dir=user_data_dir, headless=False, executable_path=executable_path, args=["--remote-debugging-port=9222"] )
4. 锁定Edge版本到历史兼容版本
如果是Edge更新导致的兼容性问题,可下载并安装2025年2月前后的Edge稳定版,然后指定该版本的executable_path路径。
5. 手动完善PyInstaller spec文件
检查生成的test.spec文件,确保Playwright的钩子资源完整加载,必要时手动调用钩子函数:
a = Analysis( 'test.py', # 其他参数保持不变 ) # 手动调用Playwright钩子确保资源打包 from playwright._impl.__pyinstaller import hook_playwright_async_api hook_playwright_async_api(a)
内容的提问来源于stack exchange,提问作者karga
相关产品推荐
相关产品推荐

