简体   繁体   中英

pygame.display.init() fails for non-root user

Tl;dr

I need to use pygame but it can't initialize the screen as a normal user because of the permissions for the framebuffer driver . root can do pygame.display.init() but not the user. User is in the group 'video' and can write on /dev/fb0 . What permission is missing to the user so pygame.display.init() would work.
Error encountered: pygame.error: Unable to open a console terminal

Description

So, I am trying to use pygame in order to display things on a framebuffer /dev/fb0 . To use some functions I need (eg pygame.Surface.convert ) the display must be initialized. However, when calling pygame.display.init() I have an error, but only when not doing so as root.

According to @Nodraak (ref) it is related to the permissions of the framebuffer driver .

Late answer but I wish I would have tried that earlier:

You may need to be root to use a frame buffer driver.

(It helped in my case: RaspberryPi 2 without X running but with a screen connected. I can now open a display through SSH or directly on the RPi)

A tree -fupg / | grep fb | grep rwx tree -fupg / | grep fb | grep rwx tree -fupg / | grep fb | grep rwx doesn't seem to show any binary which would be executable by root but not by others. I am quite sure that adding my user to a group, or tweaking the file permissions somewhere would be enough to fix the issue.

Note: For Security reasons, running the software as root is not an option.

Context

  • System: RaspberryPi
  • X Server: None
  • Screen: 1 (HDMI)
  • Connection: remote (SSH)

Origin of the error

I am trying to convert a surface with pygame.Surface.convert(...) function. But receive the following error:

pygame.error: cannot convert without pygame.display initialized

Nevertheless, initializing pygame.display with pygame.display.init() is giving the following error:

pygame.error: Unable to open a console terminal

I have the rights to write to the screen as I am part of the video group, and cat /dev/urandom > /dev/fb0 is effectively displaying snow on the screen.

Also I tried setting up the SDL_... environment variable to fbcon or dummy but it doesn't help. I also tried keeping the root env with user su -m user and same result.

Reproduce the error

On a raspberrypi without XServer, connect an HDMI screen, install pygame.

import pygame
pygame.display.init()

Error message:
pygame.error: Unable to open a console terminal

Software Versions

python     3.7.3
pygame     1.9.4.post1
OS         Raspbian Buster
libsdl     2

Related

Solution to the problem

OpenVT

So it appears that the best solution, which meet all requirement I listed, is to use openvt .

How?

The procedure holds in a few bullet points:

1. Add User to tty group

As root, add your user to the group named tty , that will allow us to give it access to the TTYs.

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

2. Give TTY access to users in group tty

Now that the user is part of the group tty we need it to be allowed to write on it, as openvt will use a tty. By default, the mode should be set at 620 we need to set it at 660 to allow the group to write on it.

# 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. Set SDL environment variables

Inside your software, make sure to set up the environment variables of SDL.

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

4. Reboot the Raspberry

Ok, you don't need a snippet for that.. Whether? Well ok.

# as root / with sudo
reboot

5. Start software with openvt

openvt (open Virtual Terminal) allows us to run the interface directly with screen access. This must be executed by the final user, in the same directory as the software (preferably).

openvt -s -- python3 ./interface.py

And that should work.
Of course you can then integrate this in a Linux service so it starts at boot. but you may need to add After: getty@tty1.service in the [Unit] section of the service file.

Well, it took me lots of time to figure that one out, so I hope it helps someone else as well.

The files in /dev/fb* are owned by root.

$ ls -l /dev/fb*
crw-rw---- 1 root video 29, 0 Jan 25 19:48 /dev/fb0
crw-rw---- 1 root video 29, 1 Jan 25 20:52 /dev/fb1

That's why You can't use it as a normal user, but only as a root as You mentioned in Your post.

As You can see, the allowed group is called video for both FrameBuffers.
Adding Your user into video group should solve Your issue:

usermod -a -G video username

I ran into the same problem trying to use pygame as a permanent display.

I decided have the pi autostart on boot, which works and starts your pygame code as root.

To activate autostart, add lines to start your code into

/etc/rc.local

above the exit 0 line.

For example (I have the code in '/opt/pygame_prototype/pg.py')

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

Then on boot, the pi will not go to the login, but start the pygame program.

Note: Use the "apt get " installed pygame without a virtual environment, the newer pip installed version failed me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM