为什么 kivy 在与 python 的 "elevate()" 函数一起使用时会失败?
Why does kivy fail when used with python's "elevate()" function?
使用elevate模块中的elevate()函数时,kivy无法启动。相关部分代码如下:
from elevate import elevate
from os import environ
environ['DISPLAY'] = ':0'
environ['KIVY_WINDOW'] = 'sdl2'
elevate()
稍后,我给出了一个 kivy 应用程序的代码并尝试 运行 它。这样做时我收到以下错误:
[INFO ] [Logger ] Record log in /root/.kivy/logs/kivy_20-10-04_91.txt
[INFO ] [Kivy ] v2.0.0rc3, git-20c14b2, 20200615
[INFO ] [Kivy ] Installed at "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/__init__.py"
[INFO ] [Python ] v3.8.5 (default, Aug 2 2020, 15:09:07)
[GCC 10.2.0]
[INFO ] [Python ] Interpreter at "/usr/bin/python3"
[INFO ] [Factory ] 185 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer, img_gif ignored)
[INFO ] [KivyMD ] 0.104.2.dev0, git-f0a8217, 2020-09-27 (installed at "/usr/local/lib/python3.8/dist-packages/kivymd-0.104.2.dev0-py3.8.egg/kivymd/__init__.py")
[INFO ] [Text ] Provider: sdl2
[INFO ] [Window ] Provider: sdl2
No protocol specified
[CRITICAL] [Window ] Unable to find any valuable Window provider. Please enable debug logging (e.g. add -d if running from the command line, or change the log level in the config) and re-run your app to identify potential causes
sdl2 - RuntimeError: b'No available video device'
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/__init__.py", line 70, in core_select_lib
cls = cls()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/window_sdl2.py", line 152, in __init__
super(WindowSDL, self).__init__()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/__init__.py", line 982, in __init__
self.create_window()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/window_sdl2.py", line 287, in create_window
self.system_size = _size = self._win.setup_window(
File "kivy/core/window/_window_sdl2.pyx", line 112, in kivy.core.window._window_sdl2._WindowSDL2Storage.setup_window
File "kivy/core/window/_window_sdl2.pyx", line 74, in kivy.core.window._window_sdl2._WindowSDL2Storage.die
[CRITICAL] [App ] Unable to get a Window, abort.
我该如何解决这个问题?我已尝试设置 environ['DISPLAY'] = '*:0'
,但收到相同的错误,只是没有“找不到协议”。请注意,这是一个应用程序,它必须 运行 在更多的机器上,而不仅仅是我自己的,所以我需要一个可以放入代码中的修复程序,而不是使用 [=27] 运行 的一次性命令=].
我还应该提一下,当我 运行 sudo python3 main.py
时,该应用程序运行良好。只有当我使用 python3 main.py
(这会导致 elevate()
函数提示我登录)时,我才会收到此错误。
失败的原因是切换到root后,没有设置DISPLAY
和XAUTHORITY
环境变量。您可以设置这些来解决该问题。这是一个可以做到这一点的示例:
def is_root():
return os.getuid() == 0
file_name = os.path.join(gettempdir(), 'f.txt')
if not is_root():
print('saving DISPLAY:', os.environ['DISPLAY'])
print('saving XAUTHORITY:', os.environ['XAUTHORITY'])
with open(file_name, mode='w') as f:
f.write(os.environ['DISPLAY'] + ' ' + os.environ['XAUTHORITY'])
else:
with open(file_name) as f:
txt = f.readline()
tokens = txt.split()
os.environ['DISPLAY'] = tokens[0]
os.environ['XAUTHORITY'] = tokens[1]
print('restored DISPLAY:', os.environ['DISPLAY'])
print('rstored XAUTHORITY:', os.environ['XAUTHORITY'])
os.remove(file_name)
这只是概念验证。您应该考虑 file_name
的安全性和选择。显然,这仅适用于 posix
系统,不适用于 Windows。我考虑过尝试使用 python tempfile
模块,但我相信任何 tempfile
写的内容都会在您有机会阅读之前被删除。我还没有测试过。
使用elevate模块中的elevate()函数时,kivy无法启动。相关部分代码如下:
from elevate import elevate
from os import environ
environ['DISPLAY'] = ':0'
environ['KIVY_WINDOW'] = 'sdl2'
elevate()
稍后,我给出了一个 kivy 应用程序的代码并尝试 运行 它。这样做时我收到以下错误:
[INFO ] [Logger ] Record log in /root/.kivy/logs/kivy_20-10-04_91.txt
[INFO ] [Kivy ] v2.0.0rc3, git-20c14b2, 20200615
[INFO ] [Kivy ] Installed at "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/__init__.py"
[INFO ] [Python ] v3.8.5 (default, Aug 2 2020, 15:09:07)
[GCC 10.2.0]
[INFO ] [Python ] Interpreter at "/usr/bin/python3"
[INFO ] [Factory ] 185 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer, img_gif ignored)
[INFO ] [KivyMD ] 0.104.2.dev0, git-f0a8217, 2020-09-27 (installed at "/usr/local/lib/python3.8/dist-packages/kivymd-0.104.2.dev0-py3.8.egg/kivymd/__init__.py")
[INFO ] [Text ] Provider: sdl2
[INFO ] [Window ] Provider: sdl2
No protocol specified
[CRITICAL] [Window ] Unable to find any valuable Window provider. Please enable debug logging (e.g. add -d if running from the command line, or change the log level in the config) and re-run your app to identify potential causes
sdl2 - RuntimeError: b'No available video device'
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/__init__.py", line 70, in core_select_lib
cls = cls()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/window_sdl2.py", line 152, in __init__
super(WindowSDL, self).__init__()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/__init__.py", line 982, in __init__
self.create_window()
File "/usr/local/lib/python3.8/dist-packages/Kivy-2.0.0rc3-py3.8-linux-x86_64.egg/kivy/core/window/window_sdl2.py", line 287, in create_window
self.system_size = _size = self._win.setup_window(
File "kivy/core/window/_window_sdl2.pyx", line 112, in kivy.core.window._window_sdl2._WindowSDL2Storage.setup_window
File "kivy/core/window/_window_sdl2.pyx", line 74, in kivy.core.window._window_sdl2._WindowSDL2Storage.die
[CRITICAL] [App ] Unable to get a Window, abort.
我该如何解决这个问题?我已尝试设置 environ['DISPLAY'] = '*:0'
,但收到相同的错误,只是没有“找不到协议”。请注意,这是一个应用程序,它必须 运行 在更多的机器上,而不仅仅是我自己的,所以我需要一个可以放入代码中的修复程序,而不是使用 [=27] 运行 的一次性命令=].
我还应该提一下,当我 运行 sudo python3 main.py
时,该应用程序运行良好。只有当我使用 python3 main.py
(这会导致 elevate()
函数提示我登录)时,我才会收到此错误。
失败的原因是切换到root后,没有设置DISPLAY
和XAUTHORITY
环境变量。您可以设置这些来解决该问题。这是一个可以做到这一点的示例:
def is_root():
return os.getuid() == 0
file_name = os.path.join(gettempdir(), 'f.txt')
if not is_root():
print('saving DISPLAY:', os.environ['DISPLAY'])
print('saving XAUTHORITY:', os.environ['XAUTHORITY'])
with open(file_name, mode='w') as f:
f.write(os.environ['DISPLAY'] + ' ' + os.environ['XAUTHORITY'])
else:
with open(file_name) as f:
txt = f.readline()
tokens = txt.split()
os.environ['DISPLAY'] = tokens[0]
os.environ['XAUTHORITY'] = tokens[1]
print('restored DISPLAY:', os.environ['DISPLAY'])
print('rstored XAUTHORITY:', os.environ['XAUTHORITY'])
os.remove(file_name)
这只是概念验证。您应该考虑 file_name
的安全性和选择。显然,这仅适用于 posix
系统,不适用于 Windows。我考虑过尝试使用 python tempfile
模块,但我相信任何 tempfile
写的内容都会在您有机会阅读之前被删除。我还没有测试过。