欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > Windows Playwright NotImplementedError问题深究

Windows Playwright NotImplementedError问题深究

2025/6/20 1:45:29 来源:https://blog.csdn.net/doupoa/article/details/148748344  浏览:    关键词:Windows Playwright NotImplementedError问题深究

原文链接:Windows Playwright NotImplementedError问题深究 < Ping通途说

0. 引言

今天来看一下这个困扰我很久的问题。是关于在FastAPI / NiceGUI 等基于Uvicorn环境下使用Async Playwright 提示NotImplementedError的问题。

本解决方案仅适用基于Uvicorn的异步环境,若需解决在Jupyter中无法使用Async Playwright的问题,请参阅:Running Playwright in JupyterLab Notebook Problem - Not implemented Error - JupyterLab - Jupyter Community Forum

1.reload来背锅吧

根本原因分析

1. Async Playwright 在 --reload 下的 NotImplementedError

  • 触发条件
    • Uvicorn 使用 --reload 时,会启动一个 文件监视子进程(通过 asyncio.create_subprocess_exec)。
    • Windows 上,asyncio 子进程管理依赖 ProactorEventLoop
    • Async Playwright 启动浏览器时,内部也会尝试创建子进程(浏览器进程),但 Windows 的事件循环策略冲突导致 NotImplementedError
  • 为什么?
    Windows 的 SelectorEventLoop 不支持子进程操作,而 ProactorEventLoop 需要显式设置。Uvicorn 的重载机制和 Playwright 的子进程创建可能使用了不同的事件循环策略,导致冲突。


2. Sync Playwright 在 --reload 下的 it looks like you are using playwright sync api inside the asyncio loop

  • 触发条件
    • Uvicorn 运行在异步事件循环中(ASGI 服务器必须是异步的)。
    • 如果在 FastAPI 路由或生命周期事件(如 @app.on_event("startup"))中直接调用 Sync Playwright,会阻塞事件循环。
    • Playwright 检测到你在异步环境中使用同步 API,抛出此错误。
  • 为什么?
    Sync Playwright 会尝试在同步上下文中运行,但 Uvicorn 的 --reload 模式已经运行在 asyncio 事件循环中,二者无法兼容。

2.要怎么解决

方案 1:禁用 --reload(最简单)

  • 适用场景:开发/生产环境均可,但失去代码热更新功能。
  • 启动方式:bash复制下载uvicorn main:app --host 0.0.0.0 --port 8000 # 去掉 --reload(或者在入口中使用Uvicorn.run("main:app",host="0.0.0.0",port=8000,reload=False)
  • 优点:无需修改代码,直接解决问题。
  • 缺点:开发时需手动重启服务。


方案 2:显式设置 WindowsProactorEventLoopPolicy(仅限 Async Playwright)

  • 适用场景:必须使用 --reload + Async Playwright。
  • 修改入口文件(main.py

import sys 
import asyncio 
from fastapi import FastAPI if sys.platform == "win32":              asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) app = FastAPI() 
@app.on_event("startup") 
async def startup(): from playwright.async_api import async_playwright playwright = await async_playwright().start() # ... 其余初始化代码

  • 优点:保留 --reload 功能。
  • 缺点:仅适用于 Async Playwright,且需确保所有 Playwright 操作都是异步的。


方案 3:Sync Playwright + 线程隔离(推荐)

  • 适用场景:必须使用 Sync Playwright + --reload
  • 实现方式

from fastapi import FastAPI 
import threading from playwright.sync_api 
import sync_playwright app = FastAPI() 
def run_sync_playwright(): with sync_playwright() as playwright: browser = playwright.chromium.launch() # ... Sync Playwright 操作 @app.on_event("startup") 
async def startup(): # 在单独线程中运行 Sync Playwright,避免阻塞事件循环 thread = threading.Thread(target=run_sync_playwright) thread.start()

  • 优点
    • 兼容 --reload
    • 不依赖事件循环策略。
  • 缺点:需要管理线程生命周期。


方案 4:换用 Linux 开发(终极方案)

  • Windows 的 asyncio 子进程管理存在限制,而 Linux/Mac 无此问题。
  • 适用场景:长期项目,可切换开发环境。
  • 优点:一劳永逸,无需处理兼容性问题。
  • 缺点:需要调整开发环境。

3.总结一下

  1. 如果只是临时开发,禁用 --reload 最简单。
  2. 如果必须用 --reload,优先 Async Playwright + ProactorEventLoop
  3. 如果坚持用 Sync Playwright,用线程隔离

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词