一直试图让 Playwright 在 Windows 上的 Jupyter 实验室中工作...Jupyter Labs 3.5.2、Python 3.9.15、Playwright 1.29.0。 代码是...
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("http://playwright.dev")
print(await page.title())
await browser.close()
await main()
错误是:
Task exception was never retrieved
future: <Task finished name='Task-5' coro=<Connection.run() done, defined at C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_connection.py:240> exception=NotImplementedError()>
Traceback (most recent call last):
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_connection.py", line 247, in run
await self._transport.connect()
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_transport.py", line 132, in connect
raise exc
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_transport.py", line 120, in connect
self._proc = await asyncio.create_subprocess_exec(
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\asyncio\subprocess.py", line 236, in create_subprocess_exec
transport, protocol = await loop.subprocess_exec(
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\asyncio\base_events.py", line 1676, in subprocess_exec
transport = await self._make_subprocess_transport(
File "C:\Users\Larry\anaconda3\envs\TDA_virtual\lib\asyncio\base_events.py", line 498, in _make_subprocess_transport
raise NotImplementedError
NotImplementedError
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
Cell In[1], line 16
13 print(await page.title())
14 await browser.close()
---> 16 await main()
Cell In[1], line 9, in main()
8 async def main():
----> 9 async with async_playwright() as p:
10 browser = await p.chromium.launch()
11 page = await browser.new_page()
File ~\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\async_api\_context_manager.py:46, in PlaywrightContextManager.__aenter__(self)
44 if not playwright_future.done():
45 playwright_future.cancel()
---> 46 playwright = AsyncPlaywright(next(iter(done)).result())
47 playwright.stop = self.__aexit__ # type: ignore
48 return playwright
File ~\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_connection.py:247, in Connection.run(self)
244 async def init() -> None:
245 self.playwright_future.set_result(await self._root_object.initialize())
--> 247 await self._transport.connect()
248 self._init_task = self._loop.create_task(init())
249 await self._transport.run()
File ~\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_transport.py:132, in PipeTransport.connect(self)
130 except Exception as exc:
131 self.on_error_future.set_exception(exc)
--> 132 raise exc
134 self._output = self._proc.stdin
File ~\anaconda3\envs\TDA_virtual\lib\site-packages\playwright\_impl\_transport.py:120, in PipeTransport.connect(self)
117 if getattr(sys, "frozen", False):
118 env.setdefault("PLAYWRIGHT_BROWSERS_PATH", "0")
--> 120 self._proc = await asyncio.create_subprocess_exec(
121 str(self._driver_executable),
122 "run-driver",
123 stdin=asyncio.subprocess.PIPE,
124 stdout=asyncio.subprocess.PIPE,
125 stderr=_get_stderr_fileno(),
126 limit=32768,
127 creationflags=creationflags,
128 env=env,
129 )
130 except Exception as exc:
131 self.on_error_future.set_exception(exc)
File ~\anaconda3\envs\TDA_virtual\lib\asyncio\subprocess.py:236, in create_subprocess_exec(program, stdin, stdout, stderr, loop, limit, *args, **kwds)
229 warnings.warn("The loop argument is deprecated since Python 3.8 "
230 "and scheduled for removal in Python 3.10.",
231 DeprecationWarning,
232 stacklevel=2
233 )
234 protocol_factory = lambda: SubprocessStreamProtocol(limit=limit,
235 loop=loop)
--> 236 transport, protocol = await loop.subprocess_exec(
237 protocol_factory,
238 program, *args,
239 stdin=stdin, stdout=stdout,
240 stderr=stderr, **kwds)
241 return Process(transport, protocol, loop)
File ~\anaconda3\envs\TDA_virtual\lib\asyncio\base_events.py:1676, in BaseEventLoop.subprocess_exec(self, protocol_factory, program, stdin, stdout, stderr, universal_newlines, shell, bufsize, encoding, errors, text, *args, **kwargs)
1674 debug_log = f'execute program {program!r}'
1675 self._log_subprocess(debug_log, stdin, stdout, stderr)
-> 1676 transport = await self._make_subprocess_transport(
1677 protocol, popen_args, False, stdin, stdout, stderr,
1678 bufsize, **kwargs)
1679 if self._debug and debug_log is not None:
1680 logger.info('%s: %r', debug_log, transport)
File ~\anaconda3\envs\TDA_virtual\lib\asyncio\base_events.py:498, in BaseEventLoop._make_subprocess_transport(self, protocol, args, shell, stdin, stdout, stderr, bufsize, extra, **kwargs)
494 async def _make_subprocess_transport(self, protocol, args, shell,
495 stdin, stdout, stderr, bufsize,
496 extra=None, **kwargs):
497 """Create subprocess transport."""
--> 498 raise NotImplementedError
NotImplementedError:
已尝试我发现的所有内容,包括使用以下注释行中的每一行修改 init .py Asyncio:
import asyncio
if sys.platform == 'win32':
from .windows_events import *
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
__all__ += windows_events.__all__
else:
from .unix_events import * # pragma: no cover
__all__ += unix_events.__all__
到目前为止没有任何乐趣...任何人的帮助将不胜感激。
我相信错误来自 Playwright _transport.py 例程的以下代码片段
try:
# For pyinstaller
env = get_driver_env()
if getattr(sys, "frozen", False):
env.setdefault("PLAYWRIGHT_BROWSERS_PATH", "0")
self._proc = await asyncio.create_subprocess_exec(
str(self._driver_executable),
"run-driver",
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=_get_stderr_fileno(),
limit=32768,
creationflags=creationflags,
env=env,
)
except Exception as exc:
self.on_error_future.set_exception(exc)
raise exc
并且我认为 JupyterLabs 的 IOLoop 是选择器事件循环策略并且不支持管道,也许是“未实现”是什么意思,但我仍在深入研究这一点,并研究这是否属实以及行为是否可以修改。
再次感谢所有输入。
你绝对走对了!Playwright 在 Windows 上的 JupyterLab 中遇到的问题,源于 JupyterLab 的事件循环(特别是
asyncio
使用的
SelectorEventLoop
)与 Playwright 建立其与浏览器进程的通信管道的方式不兼容。
Playwright 使用管道与浏览器进行通信,但 Windows 上的
SelectorEventLoop
不支持异步管道处理。因此,你会收到
NotImplementedError
。
如何解决:
虽然你不能直接在 JupyterLab 的默认事件循环中使用 Playwright,但有几种解决方法:
- 使用 Nest AsyncIOTask:
这个方法让你可以在 JupyterLab 的单线程环境中运行 Playwright 的异步代码。
```python import asyncio from playwright.async_api import async_playwright, Playwright from ipykernel.eventloops import register_integration
@register_integration('asyncio') def loop_asyncio(kernel): '''Start a kernel with asyncio event loop support.''' loop = asyncio.new_event_loop() asyncio.set_event_loop(loop)
loop.run_until_complete(kernel.do_one_iteration())
return loop
async def main(): async with async_playwright() as p: browser = await p.chromium.launch() page = await browser.new_page() await page.goto("http://playwright.dev") print(await page.title()) await browser.close()
await main() ```
- 在 JupyterLab 外部运行 Playwright 脚本:
你可以在单独的 Python 脚本中编写 Playwright 代码,然后从 JupyterLab 中调用该脚本。这让你可以充分利用 Playwright 的功能,而不会遇到事件循环问题。
- 探索替代的 Jupyter 环境:
一些 Jupyter 环境,例如 Jupyter Notebook 的经典版本或基于 QtConsole 的环境,可能支持不同的事件循环,从而与 Playwright 兼容。但是,这需要你更改 Jupyter 环境。
额外的提示:
- 确保你的 JupyterLab 和 Playwright 版本都是最新的。
- 考虑在虚拟环境中运行你的代码,以避免依赖冲突。
请尝试这些解决方法,看看哪种方法最适合你的工作流程。 祝你好运,编码愉快!
标签:python,jupyter-lab,playwright From: 75203392