launchd:Python Notifier.notify没有产生预期的输出

时间:2016-05-03 17:02:15

标签: python macos launchd

编辑:我将其缩小到python代码中Notifier.notify('Something')的问题。从launchd启动python脚本时,这不会产生预期的行为。我的其他python脚本运行正常。 / EDIT

OSX 10.11.4:当目录中的某些内容发生变化时(例如某人添加了一个文件),我试图使用launchd来运行python 3.5脚本。我使用下面的plist文件(放在〜/ Library / LaunchAgents中并使用launchctl加载),它似乎按预期使用 shell脚本

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.test.notifyme</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/notifyme.sh</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/path/to/NotifyMeDir</string>
    </array>
</dict>
</plist>

这是shell脚本:

#!/bin/bash
# notifyme.sh
osascript -e "tell application \"System Events\" to display notification \"Something\""

然而,当我将plist文件更改为:

    <key>ProgramArguments</key>
    <array>
        <string>/path/to/notifyme.py</string>
    </array>

调用以下 python 程序

#!/path/to/python3.5
# notifyme.py
from pync import Notifier

Notifier.notify('Something')

当我更改NotifyMeDir目录中的文件时,我不再获得预期的输出。

/var/log/system.log在尝试使用launchd启动.py文件时给出以下内容:

... com.apple.xpc.launchd[1] (com.test.notifyme): Service only ran for 4 seconds. Pushing respawn out by 6 seconds.

因此看起来launchd在识别目录已更改时工作正常 - 它只是没有执行python脚本

我有一个解决方法,涉及从shell脚本调用python程序。这只有在我使用&#39; osascript&#39;执行shell命令时才有效。然而,在我调用python程序之后。我已经适当地打电话给了cdmod u + x ......&#39;在shell脚本和python脚本上,它们都在launchd外部调用时工作。当使用&#34; WatchPaths&#34;以外的其他东西时它也可以正常工作。 (比如每15秒跑一次)。

以下是解决方法:

#!/bin/bash
/path/to/python /path/to/notifyme.py

osascript -e "tell application \"Finder\" to activate"

正如您所看到的,这似乎没什么可做的 我很难过。我想在不需要调用shell脚本来调用python脚本的情况下进行此运行。

2 个答案:

答案 0 :(得分:1)

好的 - 我明白了。 Pync.Notifier.notify正在对/usr/local/bin/terminal-notifier进行系统调用。程序的其余部分不等待调用它,所以程序在系统调用完成之前结束(我猜?)。无论如何,解决方案只是确保python脚本在Notifier.notify调用后有足够的内容,以便对/usr/local/bin/terminal-notifier的调用完成。 time.sleep()来电是一种有点无害的解决方法。

解决方案:

#!/path/to/python3.5
# notifyme.py
from pync import Notifier
import time

Notifier.notify('Something')
time.sleep(0.1)

答案 1 :(得分:1)

不要使用time.sleep,只需使用wait选项即可。

根据官方通知文档字符串

The options 'wait' is a boolean for whether or not we need to wait (block) for the background process to finish

所以,只需运行

pync.notify('message', wait=True)

ref:notify sourcecode