Jump to content

Updating Workflows for Monterey 12.3


Recommended Posts

There's 3 main patterns I've noticed that workflows used that need to be updated.  First and foremost, though, make sure you have both python and python3 installed (how to do that is covered elsewhere better) and that you know where they are and where they might be on other peoples' computers.  Note that every solution works for python and python3, but workflows are built in both, hence the need to have both.  I'll just use python from here on out because it's one less character :P

 

Okay, we good to go?  Let's get started.

 

Pattern 1) This is by far the most common...bash scripts in Alfred that call external python scripts, usually in the form "python script.py" or "/usr/bin/python script.py".  You have two main options to fix this, and the difference is whether you want to depend on the PATH or not.  If you want to depend on the path, then change the script to "/usr/bin/env python script.py".  It will find the python executable from PATH and use that.  The second method is below.  Note that you can add other locations python is likely to be as well.

#!/bin/bash
# ----------------------------------------------------------------------
# Find Python Binary
# ----------------------------------------------------------------------
if [ -e /usr/bin/python ]; then 
    python_binary="/usr/bin/python"
elif [ -e /opt/homebrew/bin/python ]; then
    python_binary="/opt/homebrew/bin/python"
else
    echo "Cannot find Python binary"
    exit 1
fi

# ----------------------------------------------------------------------
# Execute Code
# ----------------------------------------------------------------------
$python_binary script.py

 

Pattern 2) A python script written directly in Alfred.  To fix this is considerably more annoying if Alfred isn't picking up the binary, but it's still doable.  Here you have two main options...save it as an external Python script and then use Pattern 1, or the more annoying solution which is a bit ghetto, but still works.

#!/usr/bin/env python
#Original script
example="hi, this is my example python script."
name=input("What's your name? ")
print(example + " " + name + " is awesome!")

#!/bin/bash
#The Fix
echo "example=\"hi, this is my example python script.\"
name=input(\"What's your name? \")
print(example + \" \" + name + \" is awesome!\")" |python # Or the full path to the binary

 

Pattern 3) External python scripts which have the binary hardcoded, usually a workflow.py calling an external runner hardcoded to /usr/bin/python.  What you want to do here is create a config.py with the below code, adding other paths as well.  Then, import the config.py everywhere you need to call the binary and use PYTHON_BINARY instead of /usr/bin/python.  You'll need to do a search of the entire workflow's directory to find all instances.  Note that many workflows already contain some sort of config.py or util.py that's already imported everywhere that you can leverage.  Note that you must supply the full path to the binary.  You cannot rely on PATH inside Python itself unless you want to parse it yourself and look for the binary.  (I'm not a Python dev; there could be a more advanced way to actually use PATH, so don't take that as gospel)

#!/usr/bin/env python
# ----------------------------------------------------------------------
# Find Python Binary
# ----------------------------------------------------------------------
if os.path.exists('/usr/bin/python'):
    PYTHON_BINARY = '/usr/bin/python'
elif os.path.exists('/opt/homebrew/bin/python'):
    PYTHON_BINARY = '/opt/homebrew/bin/python'
else:
    raise Exception("Could not find python binary")

 

Bonus Pattern 4) Note that all shebangs should use /usr/bin/env python instead of /usr/bin/python, otherwise they won't run correctly because they'll be looking for a binary that doesn't exist.  You can also use the homebrew path to python, but then you run into the problem of the interpreter being other places.  /usr/bin/env will work as long as python is in the PATH.

Link to comment
11 hours ago, CandiceJoy said:

If you want to depend on the path, then change the script to "/usr/bin/env python script.py".


No need for /usr/bin/env in that context; just python script.py will work the same.

 

11 hours ago, CandiceJoy said:

You cannot rely on PATH inside Python itself


You can if you have exported PATH in the calling shell (which you should). You can also set it from inside the Python script:

 

import os

os.environ['PATH'] = '/opt/homebrew/bin:/usr/local/bin:' + os.environ['PATH']

 

11 hours ago, CandiceJoy said:

Note that all shebangs should use /usr/bin/env python instead of /usr/bin/python, otherwise they won't run correctly because they'll be looking for a binary that doesn't exist.


Good advice in general, though worth expanding (for anyone interested in the intricacies) that this only matters if you call the script as External or as ./myscript. If you python myscript, the shebang is ignored.

 

12 hours ago, CandiceJoy said:

You can also use the homebrew path to python, but then you run into the problem of the interpreter being other places. 


Which applies to Homebrew itself, even! Binaries are installed in different places on Intel and Apple Silicon.

Link to comment
  • vitor changed the title to Updating Workflows for Monterey 12.3

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