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