launchd executes python script, but import fails

2019-06-28 08:07发布

问题:

I wrote a python script using appscript to track my currently active window. I am running it via launchd, but when I do that it can't import appscript. I have set the PYTHONPATH in the plist for launchd, but I think launchd is not reading .pth files in site-packages. Is there a way to make it do that?

My script is here: https://github.com/katylava/macwintracker

This is the launchd plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>label</key>
    <string>com.katylavallee.wintracker</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/kyl/Library/Application Support/com.katylavallee.wintracker/wintracker.py</string>
        <string>1</string>
        <string>1</string>
    </array>
    <key>Environment Variables</key>
    <dict>
      <key>PYTHONPATH</key>
      <string>/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages</string>
    </dict>
    <key>StandardErrorPath</key>
    <string>/Users/kyl/Library/Logs/com.katylavallee.wintracker/wintracker_err.log</string>
    <key>StandardOutPath</key>
    <string>/Users/kyl/Library/Logs/com.katylavallee.wintracker/wintracker.log</string>
    <key>StartInterval</key>
    <integer>3</integer>
  </dict>
</plist>

And the error:

Traceback (most recent call last):
  File "/Users/kyl/Library/Application Support/com.katylavallee.wintracker/wintracker.py", line 5, in <module>
    from appscript import app, its
ImportError: No module named appscript

The python script works fine from the command line.

回答1:

Chances are that the system Python (/usr/bin/python) is being launched to execute your script rather than the MacPorts Python (/opt/local/bin/python2.6) where you have appscript installed. What should work (untested!) is to insert the MacPorts Python path as the first Program Argument, before the path to the script. And in that case you shouldn't need to specify PYTHONPATH. In theory, you might be able to make what you have work as long as the MacPorts Python was configured compatibly (i.e. similar archs, deployment targets, etc) with the system Python but you probably shouldn't want or need to go down that path.

Another approach would be to change the shebang line (the first line) of the script to an explict path to the MacPorts Python:

#!/opt/local/bin/python2.6

The reason this works in a command line shell is likely that one of your shell profile files, say .bash_profile, modifies the PATH environment variable to include the path to the MacPorts Python (/opt/local/bin) first so that /usr/bin/env python finds the MacPython python first. When run through launchd, the shell is not involved so that PATH manipulation does not happen; just the default paths are searched, meaning /usr/bin/env python executes /usr/bin/python.



回答2:

You can also use the full path to python in ProgramArguments. (More details here: Running Python Script with Launchd: imports not found)

   <key>ProgramArguments</key>
    <string>/path/to/your/python</string>
    <string>/path/to/your/script</string>