2013-06-24 53 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完整的答案是備用得的。