【问题标题】:"sh: Error: Can't open display" when I try to start a program from python“sh:错误:无法打开显示”当我尝试从 python 启动程序时
【发布时间】:2017-07-07 11:01:28
【问题描述】:

我有一个非常奇怪的问题,基本上我想从我的 Python 脚本启动 xpdf(或 Libreoffice),该脚本由 systemd-service 启动。当我从终端启动脚本时,一切正常,但是当我插入启动服务的 USB 设备时,我的系统日志中会出现此错误:

sh[2321]: Error: Can't open Display

此错误与 X11 有关,这是我的 Google 搜索告诉我的。 所以,我的问题是:如何从 Python 正确运行像 xpdf 或 libreoffice 这样的程序?

 import subprocess
 subprocess.call("/usr/bin/xpdf")

基本上就是这样。我知道这与图形环境有关,但我不知道如何解决。

【问题讨论】:

  • 你能发布你的代码吗?
  • 您是什么意思:“我插入了启动服务的 USB 设备”?你想将 xpdf 显示到直接连接到你的 Pi 的显示器上还是远程显示?
  • 目标是,当我插入 U 盘时,其上的第一个 pdf 将通过 xpdf 或 okular 显示。从 udev-rules 到 systemd-service 的一切都运行良好,除了它不会启动 xpdf、okular 或任何其他图形程序。
  • gnome 媒体处理功能不适用吗? askubuntu.com/questions/642511/…
  • 这是我的另一个想法,但最好的方法是不需要将键盘或鼠标连接到 Pi。只需启动它,插入 USB 并开始 PDF 演示文稿。

标签: python linux raspbian systemd


【解决方案1】:

X 显示系统具有非常好的安全性,可以阻止随机本地进程仅将内容显示到本地屏幕(在过去昂贵的 Sun 和 SGI 系统中,计算机实验室经常让用户远程登录到其他系统,这更是一个问题。盒子。可以有很多乐趣!)。

如果运行 xpdf 的用户与登录 X 会话的用户是同一用户,那么您只需告诉 xpdf 将其 UI 连接到何处。这通常通过将DISPLAY=:0 导出到环境来完成,这意味着“连接到第一个本地屏幕”。大多数 X 程序也支持-display :0 参数。

这样做:

/usr/bin/xpdf -display :0

或:

DISPLAY=:0 /usr/bin/xpdf

您不太可能拥有多个 X 会话,因此 :0 将在 99% 的时间内工作。

【讨论】:

  • 您可以通过调用 xhost + 来禁用 X 身份验证,但将其用作最后的手段并了解后果。
  • 没错,但他们仍然需要定义 DISPLAY 的位置。
  • 你可以;它基本上是xauth -f $user1/.Xauthority merge $user2/.Xauthority,尽管这是最粗暴的方法之一。 extract 请求一个特定的显示密钥而不是吸收所有这些密钥,generate 创建一个新密钥(这样你就可以撤销它,或者在不受信任的情况下运行它)。
  • 查看手册页; -display 中只有一个破折号,系统服务不运行配置文件,用于登录 shell。
  • 在这种情况下,我有点想知道这是否是一个单一用途的设备,您可能希望xinit xpdf /media/*/*.pdf -- :1 之类的东西只针对该特定任务启动一个单独的会话。
【解决方案2】:

由于问题是xpdf 没有找到要连接的显示器,我们有两个基本选择:查找现有显示器并进行身份验证,或者制作一个新显示器。后者通常更容易,例如:

xinit /usr/bin/xpdf -fullscreen $PDFFILE -- :2

这将启动一个新的 X 显示器 :2 只运行 xpdf,甚至不运行窗口管理器。

【讨论】:

    【解决方案3】:

    经过大约 2 周的尝试和疯狂之后,它终于奏效了。 有效的是

    os.system("DISPLAY=:0 /usr/bin/xpdf)
    

    我知道 subprocess.call 是调用程序的更好方法,但它现在似乎不起作用。 我会尝试 Yann 稍后建议的方式,但现在我只是欣喜若狂,因为它确实有效。

    谢谢大家的帮助,真的很感激!

    【讨论】:

    • 欢迎来到 StackOverflow。关键是我在回答中向您介绍了DISPLAY 的使用。我的回答深入描述了DISPLAY 的含义以及如何使用它。在你突然的脑电波回答中,你似乎忽略了一些东西。在 Stackoverflow 上,礼貌的做法是为有用的答案投票并接受解决了您所提出问题的答案。在这种情况下,这就是我的回答,它结束了你 2 周的任务。 Yann 和我都花了很多时间来写这些答案。您使用os.system 的事实既不存在也不存在。
    • subprocess.call可能缺少shell=True,否则需要自己拆分参数,包括设置环境变量(可能通过os.environ或subprocess.Popen)。
    猜你喜欢
    • 1970-01-01
    • 2014-12-04
    • 2019-11-05
    • 2019-01-10
    • 2017-09-12
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多