使用 python3 打开 Web 浏览器时出现错误“tcgetpgrp failed: Not a tty”

Gha*_*eak 7 python python-3.x python-webbrowser wsl-2

以下是我的 Windows WSL 环境的细分:

  • 视窗11
  • WSL 版本 2
  • Ubuntu 版本 20.04.3 LTS
  • Python 3.8.10

我有一个超级简单的 Python 程序,用于在默认浏览器中打开网页。

这是我的代码:

import webbrowser

webbrowser.open('https://github.com')
Run Code Online (Sandbox Code Playgroud)

当我从终端运行此命令时,网页会按预期打开,但我也在终端中收到此错误:

tcgetpgrp failed: Not a tty

当我的终端显示此消息时,光标会向下移动到下一行,看起来好像进程已挂起或发生其他情况。为了能够使用终端,我必须Ctrl+C才能让它给我命令提示符。

我寻找答案,我能找到的所有内容都与使用 Jupyter 或 PHP 有关,但我没有使用它们中的任何一个,我只是使用普通的旧 Python 来尝试打开浏览器。

谁能告诉我这里的问题是什么以及如何解决这个问题/防止它发生?

Not*_*1ds 9

是的,我还可以在 WSL 下从 Ubuntu 上的 Python(和 IPython)REPL 重现它。至少在交互运行时我没有遇到需要Ctrl+的“锁定”。C

我将对“为什么”进行理论分析。其中大部分内容我可以自己确认,但下面的最后一条对我来说仍然有点神秘:

  • webbrowser-open首先使用环境变量定义的任何浏览器BROWSER,但回退到 (我相信) xdg-open

  • xdg-openalternatives使用系统中为x-www-browser或定义的任何浏览器www-browser

  • 在 WSL 上的 Ubuntu 20.04 上,wslu默认安装该软件包(但在 22.04 下它不再是默认软件包)。

  • 该软件包包括wslview助手。从它的联机帮助页来看:

    [wslview] 是 WSL 上的文件查看器,允许您在 Windows 中打开 WSL 中的文件和文件夹,也是一个假 Web 浏览器,允许在 Windows 10 上的默认浏览器中打开 URL。

  • wslview在安装过程中注册为和wslu的替代项。x-www-browserwww-browser

  • webbrowser.open不只是调用 xdg-open,而是尝试获取结果浏览器的进程信息,以便它可以(至少)在请求时提升窗口。其中一部分显然是通过tcgetpgrp系统调用获取进程组。根据tcgetpgrp手册页:

    该函数tcgetpgrp()返回与 fd 关联的终端上的前台进程组的进程组 ID,该终端必须是调用进程的控制终端。

  • 这是我必须“手动挥手”的地方 -从 到到(允许启动 Windows 可执行文件的内核系统)的交接中的某些内容“丢失”或重定向了终端的文件描述符,导致这条信息。webbrowser.openwslviewbinfmt_misc

    在我看来,这是 的一个错误(意外的副作用?)wslview,因为确保不使用它可以防止错误发生。

作为解决方法,可以:

  • export BROWSER=/mnt/c/path/to/windows/browser在开始Python之前。请注意,我不确定如何指向 Edge,因为据我所知,它没有“.exe”(它是通用/现代/UWP/任何应用程序)。

  • 或者,由于您使用的是 Windows 11,请安装 Linux 浏览器。我使用 Vivaldi 进行测试并确认它可以在 WSL 下从 Python 正确打开。请注意,您不能sudo apt install在 WSL 下使用 Chromium 或 Firefox,因为它们都是 Snap。