2013-06-24 52 views
1

我有一个Python 3脚本,它从URL获取一些JSON并对其进行处理,并在我得到的数据有任何重大更改时通知我。我试过使用notify2PyGObject的libnotify绑定(gi.repository.Notify),并用任一方法得到类似的结果。这个脚本在终端运行时运行正常,但当cron试图运行它时会产生窒息。现在使用libnotify的Python 3脚本作为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() 

,如果我创建与字符串列表调用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 

...如果我改变它调用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 

我做了一些研究,看到建议把PATH=到我的crontab,或出口$DISPLAY(我这样做是在脚本中调用os.system('export DISPLAY=:0')),但没有造成任何变化......

回答

4

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

我想你crontab -e编辑cron和入境看起来是这样的:

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)

+0

将导出添加到cron作业本身修复了它!谢谢! 另外我想我会抛出,我通常在可执行的Python 3.x脚本中使用这个shebang:'#!/ usr/bin/env python3' –

2

如果你想从你这样的蟒蛇内设置DISPLAY与os.system('export DISPLAY=:0') ttempted,你可以做这样的事情

import os 

if not 'DISPLAY' in os.environ: 
    os.environ['DISPLAY'] = ':0' 

这将尊重任何显示用户可能对多座箱,并退回到主头:0。

0

如果乌尔通知功能,无论Python版本或通知库,不跟踪通知ID [在Python列表],并删除最早前的队列完全充满或错误,则取决于DBUS设置(在Ubuntu它是21通知最大)dbus会抛出一个错误,达到最大通知!

from gi.repository import Notify 
from gi.repository.GLib import GError 

# Normally implemented as class variables. 
DBUS_NOTIFICATION_MAX = 21 
lstNotify = [] 

def notify_show(strSummary, strBody, strIcon="dialog-information"): 
    try: 
     # full queue, delete oldest 
     if len(lstNotify)==DBUS_NOTIFICATION_MAX: 
      #Get oldest id 
      lngOldID = lstNotify.pop(0) 
      Notify.Notification.clear(lngOldID) 
      del lngOldID 
      if len(lstNotify)==0: 
       lngLastID = 0 
      else: 
       lngLastID = lstNotify[len(lstNotify) -1] + 1 
       lstNotify.append(lngLastID) 
       notify = Notify.Notification.new(strSummary, strBody, strIcon) 
       notify.set_property('id', lngLastID) 
       print("notify_show id %(id)d " % {'id': notify.props.id}) 
       #notify.set_urgency(Notify.URGENCY_LOW) 
       notify.show() 
    except GError as e: 
     # Most likely exceeded max notifications 
     print("notify_show error ", e) 
    finally: 
     if notify is not None: 
      del notify 

尽管可能以某种方式询问dbus通知队列的最大限制是什么。也许有人可以帮助...改善这一点,直到完美。

PLZ

曲子gi.repository完整的答案是备用得的。