Jump to content

Probelm with $PATH in Alfred for Python script


Recommended Posts

Posted

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()
bump.write(str(proc))
bump.close()

and found the following:

/usr/bin:/bin:/usr/sbin:/sbin

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!

Posted (edited)

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

/usr/bin:/bin:/usr/sbin:/sbin:/opt/random/bin

via...

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
Posted
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
    else:
        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.

Posted (edited)

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:

 

DELIMITER = '➜'
'/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
DELIMITER = '➜'
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

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...