python-notify模块与cron: gio.Error

1 投票
2 回答
771 浏览
提问于 2025-04-18 11:26

我在寻求一些帮助,想用 python-crontab 来显示通知,因为我尝试过的所有方法都不管用。当脚本通过 cron 启动时,显示没有初始化。但是当我手动启动它时,一切正常。

    #!/usr/bin/env python
    # coding: utf8

    import subprocess
    import os

    #os.environ.setdefault("XAUTHORITY", "/home/guillaume" + "/.Xauthority")

    #os.environ.setdefault('DISPLAY', ':0.0')     # do not work
    #os.environ['DISPLAY'] = ':0.0'               # do not work
    print = os.environ

    cmd2 = 'notify-send test'
    subprocess.call(cmd2, shell=True)

    # more code, which is working (using VLC)
    cmd3 = "cvlc rtp://232.0.2.183:8200 --sout file/mkv:/path/save/file.mkv" # to download TV's flow
    with open("/path/debug_cvlc.log", 'w') as out:
        proc = subprocess.Popen(cmd3, stderr=out, shell=True, preexec_fn=os.setsid)
    pid = proc.pid                  # to get the pid
    with open("/path/pid.log", "w") as f:
       f.write(str(pid))            # to write the pid in a file
    # I'm using the pid to stop the download with another cron's task, and to display another notify message. 
    # Download and stop is working very well, and zenity too. But not notify-send

谢谢

编辑:这是我为这个 cron 脚本设置的环境变量:

{'LANG': 'fr_FR.UTF-8', 'SHELL': '/bin/sh', 'PWD': '/home/guillaume', 'LOGNAME': 'guillaume', 'PATH': '/usr/bin:/bin', 'HOME': '/home/guillaume', 'DISPLAY': ':0.0'}

编辑2:我在 cron 中调用我的脚本是这样的:

45 9 30 6 * export DISPLAY=:0.0 && python /home/path/script.py > /home/path/debug_cron_on.log 2>&1

我想说明一下,我有两个屏幕,所以我认为 DISPLAY:0.0 是显示这个通知的正确方式……但我看不到它。

编辑3:看来我在使用 notify-send 时遇到了问题,因为用 zenity 是可以的:

subprocess.call("zenity --warning --timeout 5 --text='this test is working'", shell=True)

我有 notify-send 版本 0.7.3,并且我想说明 notify-send 在终端中是可以工作的。

编辑4:接下来尝试使用 python-notify。

import pynotify
pynotify.init("Basic")
n = pynotify.Notification("Title", "TEST")
n.show()

日志文件显示这个:(法语)

    Traceback (most recent call last):
      File "/home/path/script.py", line 22, in <module>
        n.show()
    gio.Error: Impossible de se connecter : Connexion refusée 
 #Translating: Unable to connect : Connection refused

所以,我在 dbus 上有问题?这是什么?

解决方案:在创建 cron 任务之前获取 DBUS_SESSION_BUS_ADDRESS:

cron = CronTab()
dbus = os.getenv("DBUS_SESSION_BUS_ADDRESS")   # get the dbus
# creating cron  
cmd_start = "export DBUS_SESSION_BUS_ADDRESS=" + str(dbus) + " && export DISPLAY=:0.0 && cd /path && python /path/script.py > path/debug_cron.log 2>&1"
job = cron.new(cmd_start)
job = job_start.day.on(self.day_on) # and all the lines to set cron, with hours etc..
cron.write()             # write the cron's file

最后,cron 的命令是这样的:

20 15 1 7 * export DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-M0JCXXbuhC && export DISPLAY=:0.0 && python script.py

然后通知就显示出来了。问题解决了!! :)

2 个回答

0

crontab被认为是一个外部主机——它没有权限写入你的显示屏。

解决方法:允许任何人写入你的显示屏。登录后在你的命令行中输入以下内容:

xhost +
1

你正在这样调用定时任务:

45 9 30 6 * DISPLAY=:0.0 python /home/path/script.py > /home/path/debug_cron_on.log 2>&1

这样是不对的,因为你没有设置DISPLAY这个变量,后面的命令就不会执行。

试试这个:

45 9 30 6 * export DISPLAY=:0.0 && cd /home/path/ && python script.py >> debug_cron.log 2>&1

另外,你在定时任务中也设置了DISPLAY变量,所以可以尝试一下不在任务行中导出它,看看定时任务能否正常工作。

45 9 30 6 * cd /home/path/ && python script.py >> debug_cron.log 2>&1

编辑

在调试的时候,可以让定时任务每分钟运行一次。以下这个对我有效:

定时任务条目:

* * * * *  cd /home/user/Desktop/test/send-notify && python script.py

script.py

#!/usr/bin/env python

import subprocess
import os

os.environ.setdefault('DISPLAY', ':0.0')
print os.environ

cmd2 = 'notify-send test'
subprocess.call(cmd2, shell=True)

编辑 2

使用pynotify后,script.py变成:

#!/usr/bin/env python

import pynotify
import os

os.environ.setdefault('DISPLAY', ':0.0')

pynotify.init("Basic")
n = pynotify.Notification("Title", "TEST123")
n.show()

而定时任务条目变成:

* * * * *  cd /home/user/Desktop/test/send-notify && python script.py

编辑 3

定时任务环境中缺少一个环境变量DBUS_SESSION_BUS_ADDRESS。可以通过这种方式这种方式来设置它。

撰写回答