Jump to content

Probelm with $PATH in Alfred for Python script

Recommended Posts

I've run into a problem when trying to execute a Python script in Alfred.

The script is basically running a subprocess using a program located at /opt/random/bin/.

When I run the script, I get the following debug.


[ERROR: alfred.workflow.action.script] Code 127: /bin/bash: /opt/random/bin/tool "/Users/ritashugisha/Downloads/file.txt" "/Users/ritashugisha/Downloads/new.txt": No such file or directory


So I looked at the $PATH that Alfred was using...

bump = open('/Users/ritashugisha/Desktop/path.txt', 'w')
proc = subprocess.Popen(['echo $PATH'], stdout = subprocess.PIPE, shell = True)
(proc, proc_e) = proc.communicate()

and found the following:


This doesn't include what I need it to include.

So do you have any ideas for tricks to get around this? Or am I approaching this the wrong way?


Thanks for any help you provide!

Link to comment

So I've fixed the $PATH to also use the /opt/random/bin path as well...



os.environ['PATH'] = '%s:/opt/random/bin' % os.environ['PATH']

But for some reason I'm still getting the Alfred debug error and my script is still not working.

Edited by Ritashugisha
Link to comment
import os, sys
import ToolUtil

def convertSelect(query):
    if len(query) > 0 and query[0] == '.':
        query = query[1:]
    feed = ToolUtil.Feedback() # Feedback for Script Filter
    item = ToolUtil.getFinderSelection() # Gets the current selected item in Finder via Applescript
    formatFound = False
    if os.path.splitext(item)[1][1:].lower() in ToolUtil.SUPPORTED_FORMATS: # Checks if the selected item in Finder is in an array of legal extensions
        for i in ToolUtil.SUPPORTED_FORMATS:
            if query.lower() in i:
                feed.add_item(u'%s \u279c .%s' % (os.path.basename(item), i),
                    'Convert to %s' % i,
                    'tool "%s" "%s"' % (item, '%s.%s' % (os.path.splitext(item)[0], i)), # Script filter argument
                    '', '', 'icon.png')
                formatFound = True
        feed.add_item('Selection cannot be converted', '', '', '', '', 'icon.png')
        formatFound = True
    if not formatFound:
        feed.add_item('Format .%s does not exist' % query, '', '', '', '', 'icon.png')
    return feed

The feedback is then listed in the script filter, and whatever the user selects from the script filter gets passed to the following method...

import os, subprocess
os.environ['PATH'] = '%s:/opt/random/bin' % os.environ['PATH']
proc = subprocess.Popen(['{query}'], stdout = subprocess.PIPE, shell = True)
(proc, proc_e) = proc.communicate()
return proc

Hope this helps.

Link to comment

Yeah, the problem is in the way you're passing stuff to subprocess.Popen.

First of all, you really shouldn't be using shell=True unless absolutely necessary. Here it isn't. Use the full path of the executable instead.

With subprocess.Popen (and .call, .check_output etc.), you're supposed to pass the program as the first item in the args list and subsequent arguments in the rest of args. You don't mash them all together like with os.system or the exec functions in other languages. The error you were getting is because you're passing "/Users/ritashugisha/Downloads/file.txt" "/Users/ritashugisha/Downloads/new.txt" as a single argument (and hence filepath), not two separate arguments.

If you absolutely have to pass multiple arguments in one {query}, this line:


'tool "%s" "%s"' % (item, '%s.%s' % (os.path.splitext(item)[0], i))
should look something more like this:


'/full/path/to/tool {0} {1} {0} {2}.{3}'.format(DELIMITER, item, os.path.splitext(item)[0], i)
(I don't know if you've got from __future__ import unicode_literals at the top of your script, but if you haven't this code will break, as will your code with non-ASCII data. Change DELIMITER = '➜' to DELIMITER = u'➜' if you don't want it to break immediately, add from __future__ import unicode_literals (or prepend every literal strings with u) if you don't want your code to break with non-ASCII input, too.)

And the following script should split the query into the individual arguments and pass those to subprocess.Popen:


import subprocess
args = [s.strip() for s in '{query}'.split(DELIMITER)]
proc = subprocess.Popen(args, stdout=subprocess.PIPE)
(proc, proc_e) = proc.communicate()
return proc
Note: I'm drunk and haven't tested my code. No liability is accepted for errors in my code, but the basis of the error is 100% correct. I guarantee it!

If it's not working at all, ask me again, and I'll sort it out in ~8 hours or so when I'm sober ;)

Also, it's perhaps worth adding that your code formatting isn't compliant with PEP8 (no extra spaces around = in assignments, for example). It's not a big deal—not by a long way—but it's kinda expected.

Edited by deanishe
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...