EDIT: I narrowed it down to an issue with Notifier.notify('Something')
in the python code. This does not produce the expected behavior when the python script is started from launchd. My other python scripts work fine. /EDIT
OSX 10.11.4: I am trying to use launchd to run a python 3.5 script when something in directory changes (e.g. somebody adds a file). I use the following plist file (placed in ~/Library/LaunchAgents and loaded with launchctl), and it seems to work as expected with a shell script
<?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>
This is the shell script:
#!/bin/bash
# notifyme.sh
osascript -e "tell application \"System Events\" to display notification \"Something\""
However, when I change the plist file to have:
<key>ProgramArguments</key>
<array>
<string>/path/to/notifyme.py</string>
</array>
Which calls the following python program
#!/path/to/python3.5
# notifyme.py
from pync import Notifier
Notifier.notify('Something')
I no longer get the expected output when I change a file in the NotifyMeDir directory.
/var/log/system.log gives the following when trying to launch the .py file with launchd:
... com.apple.xpc.launchd[1] (com.test.notifyme): Service only ran for 4 seconds. Pushing respawn out by 6 seconds.
so it looks like launchd is working fine in recognizing that the directory changed - it's just not executing the python script.
I have a workaround that involves calling the python program from the shell script. This only works if I execute a shell command using 'osascript' after I call the python program, however. I have appropriately called 'cdmod u+x ...' on both the shell script and the python script, and they both work when called on their own outside of launchd. It also works fine when using with something other than "WatchPaths" (such as running every 15 seconds).
Here is the workaround:
#!/bin/bash
/path/to/python /path/to/notifyme.py
osascript -e "tell application \"Finder\" to activate"
As you can see, this doesn't seem to have anything to do I'm stumped. I'd like to have this run without needing to call a shell script in order to call a python script.
Don't use time.sleep
, just use the wait
options.
According to the official notify docstring
The options 'wait' is a boolean for whether or not we need to wait (block) for the background process to finish
so, just run as
pync.notify('message', wait=True)
ref: notify sourcecode