使用libnotify的Python 3脚本作为cron作业失败

p0l*_*ear 2 dbus pygobject libnotify python-3.x

我有一个Python 3脚本,从URL获取一些JSON,处理它,并通知我,如果我得到的数据有任何重大变化.我尝试过使用notify2PyGObject的libnotify绑定(gi.repository.Notify),并用这两种方法得到类似的结果.当我从终端运行它时,这个脚本工作正常,但是当cron尝试运行它时会窒息.

import notify2
from gi.repository import Notify

def notify_pygobject(new_stuff):
    Notify.init('My App')
    notify_str = '\n'.join(new_stuff)
    print(notify_str)
    popup = Notify.Notification.new('Hey! Listen!', notify_str,
                                    'dialog-information')
    popup.show()

def notify_notify2(new_stuff):
    notify2.init('My App')
    notify_str = '\n'.join(new_stuff)
    print(notify_str)
    popup = notify2.Notification('Hey! Listen!', notify_str,
                                 'dialog-information')
    popup.show()
Run Code Online (Sandbox Code Playgroud)

现在,如果我创建一个notify_pygobject使用字符串列表调用的脚本,cron会通过邮件假脱机将此错误抛回给我:

Traceback (most recent call last):
  File "/home/p0lar_bear/Documents/devel/notify-test/test1.py", line 3, in <module>
    main()
  File "/home/p0lar_bear/Documents/devel/notify-test/test1.py", line 4, in main
    testlib.notify(notify_projects)
  File "/home/p0lar_bear/Documents/devel/notify-test/testlib.py", line 8, in notify
    popup.show()
  File "/usr/lib/python3/dist-packages/gi/types.py", line 113, in function
    return info.invoke(*args, **kwargs)
gi._glib.GError: Error spawning command line `dbus-launch --autolaunch=776643a88e264621544719c3519b8310 --binary-syntax --close-stderr': Child process exited with code 1
Run Code Online (Sandbox Code Playgroud)

...如果我将其改为拨打电话notify_notify2():

Traceback (most recent call last):
  File "/home/p0lar_bear/Documents/devel/notify-test/test2.py", line 3, in <module>
    main()
  File "/home/p0lar_bear/Documents/devel/notify-test/test2.py", line 4, in main
    testlib.notify(notify_projects)
  File "/home/p0lar_bear/Documents/devel/notify-test/testlib.py", line 13, in notify
    notify2.init('My App')
  File "/usr/lib/python3/dist-packages/notify2.py", line 93, in init
    bus = dbus.SessionBus(mainloop=mainloop)
  File "/usr/lib/python3/dist-packages/dbus/_dbus.py", line 211, in __new__
    mainloop=mainloop)
  File "/usr/lib/python3/dist-packages/dbus/_dbus.py", line 100, in __new__
    bus = BusConnection.__new__(subclass, bus_type, mainloop=mainloop)
  File "/usr/lib/python3/dist-packages/dbus/bus.py", line 122, in __new__
    bus = cls._new_for_bus(address_or_type, mainloop=mainloop)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
Run Code Online (Sandbox Code Playgroud)

我做了一些研究,并看到了建议将一个PATH=放入我的crontab,或者导出$DISPLAY(我通过调用在脚本中做了这个os.system('export DISPLAY=:0'))但是没有导致任何改变......

Hav*_*vok 6

你走在正确的轨道上.这种行为是因为cron在多用户无头环境中运行(将其视为在没有GUI的终端中以root身份运行,有点),因此他不知道显示什么(X Window Server会话)和用户目标.如果您的应用程序打开,例如,窗口或通知某些用户桌面,则会出现此问题.

我想你编辑你的cron,crontab -e条目看起来像这样:

m h dom mon dow command

就像是:

0 5 * * 1 /usr/bin/python /home/foo/myscript.py

注意我使用Python的完整路径,如果PATH环境变量可能不同的这种情况则更好.

然后改为:

0 5 * * 1 export DISPLAY=:0 && /usr/bin/python /home/foo/myscript.py

如果这仍然不起作用,您需要允许您的用户控制X Windows服务器:

添加到您的.bash_rc:

xhost +si:localuser:$(whoami)