2013-06-24 6 views
1

URL에서 일부 JSON을 가져 와서 처리하고, 데이터가 크게 변경되면 알려주는 Python 3 스크립트가 있습니다. 나는 notify2PyGObject의 libnotify 바인딩 (gi.repository.Notify)을 사용해 보았으며 두 가지 방법으로 비슷한 결과를 얻었습니다. 이 스크립트는 터미널에서 실행할 때 a-ok로 작동하지만 cron이 실행하려고 할 때 찌를 때 사용합니다. 내가 문자열 목록으로 notify_pygobject를 호출하는 스크립트를 작성하는 경우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() 

이제 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 

을 나는 (몇 가지 조사를하고 제안을 내 crontab을에 PATH=을 넣어, 또는 $DISPLAY을 수출했다 나는 스크립트 내에서 os.system('export DISPLAY=:0')로 전화하여이 작업을 수행했으나 아무 변화도 없었습니다 ...

답변

4

당신은 올바른 길을 가고 있습니다. 이 동작은 cron이 멀티 유저 헤드리스 환경에서 실행되기 때문에 (GUI가없는 터미널에서 루트로 실행되는 것처럼 생각하기 때문에) 어떤 디스플레이 (X 윈도우 서버 세션)와 사용자가 대상인지 알지 못합니다. 예를 들어 응용 프로그램이 열려 있거나 일부 사용자 데스크톱에 알림이 표시되면이 문제가 발생합니다.

난 당신이 crontab -e로 크론을 편집 가정 및 항목은 다음과 같습니다 :

m h dom mon dow command

뭔가 같은 : 나는 파이썬의 전체 경로를 사용

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

주이며, PATH 환경 변수가 다를 수있는 이런 종류의 상황에서 더 좋습니다. 이것은 여전히 ​​사용자가 X Windows 서버 제어 할 수 있도록 할 필요가 작동하지 않으면

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

:

은 그럼 그냥 변경 에 추가

당신의 .bash_rc :

xhost +si:localuser:$(whoami)

+0

cron 작업 자체에 내보내기를 추가하여 수정했습니다! 고맙습니다! 또한 나는이 스크립트를 실행 파일 python 3.x에서 보통 사용한다고 생각했다 :'#!/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

파이썬 버전이나 알림 라이브러리에 상관없이 ur notify 함수가 파이썬 목록의 알림 ID를 추적하지 않고 대기열이 완전히 찼거나 오류가 발생하기 전에 가장 오래된 것을 삭제하지 않으면 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 완전한 답변은 구하기 예비 있습니다.