【问题标题】:pygame.display.init() fails for non-root userpygame.display.init() 对于非 root 用户失败
【发布时间】:2022-06-10 20:29:01
【问题描述】:

Tl;博士

我需要使用pygame,但由于帧缓冲驱动程序的权限,它无法以普通用户身份初始化屏幕。 root 可以做pygame.display.init() 但不是用户。用户在“视频”组中,可以在/dev/fb0 上写字。用户缺少什么权限,所以 pygame.display.init() 可以工作。
遇到错误:pygame.error: Unable to open a console terminal

说明

所以,我正在尝试使用 pygame 来在帧缓冲区 /dev/fb0 上显示内容。 要使用我需要的某些功能(例如pygame.Surface.convert),必须初始化显示。但是,当调用pygame.display.init() 时出现错误,但仅限于不以 root 身份调用时。

根据@Nodraak (ref),这与framebuffer driver的权限有关。

迟到的答案,但我希望我早点尝试过:

您可能需要 root 才能使用帧缓冲区驱动程序。

(在我的情况下它有所帮助:RaspberryPi 2 没有运行 X,但有一个 屏幕连接。我现在可以通过 SSH 或直接在 RPi)

tree -fupg / | grep fb | grep rwx 似乎没有显示任何可由 root 执行但不能由其他人执行的二进制文件。我很确定将我的用户添加到组中,或在某处调整文件权限就足以解决问题。

注意:出于安全原因,不能以 root 身份运行该软件。

上下文

  • 系统:树莓派
  • X 服务器:无
  • 屏幕:1 (HDMI)
  • 连接:远程 (SSH)

错误来源

我正在尝试使用pygame.Surface.convert(...) 函数转换表面。但收到以下错误:

pygame.error: cannot convert without pygame.display initialized

尽管如此,使用 pygame.display.init() 初始化 pygame.display 会出现以下错误:

pygame.error: Unable to open a console terminal

由于我是video 组的一员,我有权在屏幕上写字,cat /dev/urandom > /dev/fb0 正在有效地在屏幕上显示雪。

我还尝试将 SDL_... 环境变量设置为 fbcondummy,但它没有帮助。我还尝试将 root 环境与用户 su -m user 保持一致,结果相同。

重现错误

在没有 XServer 的 raspberrypi 上,连接 HDMI 屏幕,安装 pygame。

import pygame
pygame.display.init()

错误信息:
pygame.error: Unable to open a console terminal

软件版本

python     3.7.3
pygame     1.9.4.post1
OS         Raspbian Buster
libsdl     2

相关

【问题讨论】:

  • 你试过更新pygame吗?您可以从 Piwheels 项目下载轮子:piwheels.org/project/pygame,或从源代码构建。 (或者从 pip 下载一个轮子,但我不确定 Rpi 与其他 Linux 有何不同)。
  • 尝试将 SDL_VIDEODRIVER 变量设置为 directfb。如果它不起作用,请尝试 rpikmsdrm
  • 好的,我会试试这个。但问题是它以 root 身份工作,所以我认为这不应该是库的问题????
  • 关于 SDL_VIDEODRIVER 这并没有解决问题。将 pygame 更新到 2.1.2 版也没有帮助。还有其他想法吗?
  • @vinalti:如果您描述用例可能会有所帮助。我遇到了与您相同的问题,并认为不值得尝试这种方式。我最终设置了自动启动,以便 pi 用户直接启动到 pygame(因为这是我的目标,我想将 pi 用作永久显示) - 这适用于安装在 pi 上的 pygame,带有“apt获取...”命令(安装 1.9.4.post1),但(对我而言)没有安装 pygame 的“pip”。

标签: python pygame raspberry-pi sdl-2 framebuffer


【解决方案1】:

我在尝试使用 pygame 作为永久显示时遇到了同样的问题。

我决定让 pi 在启动时自动启动,它可以运行并以 root 身份启动您的 pygame 代码。

要激活自动启动, 添加行以开始您的代码

/etc/rc.local

exit 0 行上方。

例如(我在'/opt/pygame_prototype/pg.py'中有代码)

cd /opt/pygame_prototype
/usr/bin/python3 pg.py

然后在开机时,pi 不会去登录,而是启动 pygame 程序。

注意:在没有虚拟环境的情况下使用“apt get”安装的pygame,较新的pip安装版本失败了。

【讨论】:

  • 但是它以 root 身份运行,而不是以用户身份运行?
  • 是的,但是如果你停止它,它就会停止以 root 身份运行并且你是 pi 用户。这取决于您的用例,如果有一个 pi 需要显示内容或仅允许通过 pygame 进行交互,则以 root 身份运行它以访问缓冲区是有意义的
  • 出于安全原因,我根本无法以 root 身份运行它,我需要为特定用户添加正确的权限,以便他有足够的权限来运行界面,不多也不少。 ://
  • 嗯,你的 pi 以 root 身份运行很多服务,所以这只是其中之一。好的 - 看起来您需要更多地描述您的用例(例如服务如何启动以及如果它结束会发生什么)。我在物理门使用 pygame 来显示诸如“访问权限”、“禁止访问”、“扫描您的票以进入”之类的信息——因此以 root 身份运行是安全的。顺便说一句,我花了半天时间研究这个,如果我找到更好的解决方案,我会更新答案。
  • 非常感谢。我的代理上仍然有这个问题(因为我自己的接口需要它)并且会为此困扰一些 Linux 专家。如果我找到一个迟到的解决方案,我会按照承诺更新答案。
【解决方案2】:

问题的解决方法

OpenVT

看来,满足我列出的所有要求的最佳解决方案是使用openvt

如何?

该程序包含几个要点:

1。将用户添加到tty

以 root 身份,将您的用户添加到名为 tty 的组中,这将允许我们为其授予对 TTY 的访问权限。

# As root:
usermod -a -G tty $username

2。向tty 组中的用户授予 TTY 访问权限

现在用户是tty 组的一部分,我们需要允许它在上面写,因为openvt 将使用tty。默认情况下,模式应设置为620,我们需要将其设置为660,以允许组在其上写入。

# Edit file: /lib/udev/rules.d/50-udev-default.rules
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0660"
#                                      ensure mode is 0660  ^

3。设置 SDL 环境变量

在您的软件中,确保设置 SDL 的环境变量。

import os
# ...
os.environ['SDL_VIDEODRIVER'] = 'fbcon'
os.environ["SDL_FBDEV"] = "/dev/fb0"

4。重启树莓

好吧,你不需要 sn-p 来做这件事.. 是否?好吧。

# as root / with sudo
reboot

5。用openvt启动软件

openvt(打开虚拟终端)允许我们通过屏幕访问直接运行界面。这必须由最终用户在与软件相同的目录中执行(最好)。

openvt -s -- python3 ./interface.py

这应该可行。
当然,您可以将其集成到 Linux 服务中,以便它在启动时启动。但您可能需要在服务文件的[Unit] 部分添加After: getty@tty1.service

嗯,我花了很多时间才弄清楚这一点,所以我希望它也能对其他人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-26
    • 2017-02-21
    • 2021-05-28
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 2021-11-26
    • 2019-11-25
    相关资源
    最近更新 更多