Launch PsychoPy From Terminal

What is the command to launch a PsychoPy experiment from the Terminal on a Mac? I have multiple versions of the PsychoPy application on the same machine, so it is important that the correct one opens for a given experiment.

For example, if I have an experiment named study.psyexp and want to open it using a version of the application I have named PsychoPy2.1.81.10 from the terminal, what would the command be?

Hi Jenny,
as you might know, PsychoPy comes with its own independent python environment, so first you need to set that environment as your python working environment (see attachment). Secondly, you need to convert the study.psyexp XML script, into a .py module, from within the environment (see the bite of code below). Finally, run it (from within the environment).

from psychopy.app.builder import experiment
import codecs

exp = experiment.Experiment(prefs = None)
exp.loadFromXML(xmlExpFile)
scriptObj = exp.writeScript(xmlExpFile)
if scriptObj is None:
    raise RuntimeError('No script generated for %s' %xmlExpFile)    
codecs.open(pyExpFile, 'w', 'utf-8').write(scriptObj.getvalue())

PsychoPyPython.py (5.1 KB)

Hope this helps.
Cheers,
Luca

Hi there,
I just realized that the question was probably far simpler than what I understood. Here’s the answer

open -a /Applications/PsychoPy2.1.81.10.app study.psyexp

provided that PsychoPy2.1.81.10.app is normally installed in the Applications directory and you run the command from the directory where study.psyexp is.

Also, you can run multiple instances of the same application adding “-n” to the command line. For example, you could open 2 experiments:

open -a /Applications/PsychoPy2.1.81.10.app study1.psyexp
open -n -a /Applications/PsychoPy2.1.81.10.app study2.psyexp

That said, the good thing about my previous solution is that with it one can open & run the experiment right away and can easily run a battery of tests, one test after the other with no interruption.

Maybe a future version of PsychoPy will manage a command line option to do the same.

Cheers,
L.

Thank you for your responses! I appreciate you taking the time to provide detailed information. This is a huge help.

Hi Luca,
I have been struggling for some time to standardize our lap computers and have them all run psychopy scripts form the command line. We have had mixed results (even creating a specific conda env that works on one laptop, but then won’t run the same script on another). This has resulted in us giving up on trying to run our task scripts from the command line and just opening them within psychopy so the program handles all the requirements and doesn’t break with one version of a library, but run fine with another.

This is problematic, however, because this opens the scripts up to accidental editing. I saw this post and your workaround of setting the psychopy environment aounds great (to be honest I didn’t know this was possible). I tried your script attached here and have a usage question.

All the input arguments make sense except the env and arguments. Is there any chance you can provide a usage example? I thought the -e argument was just to name the env, but it’s asking for 3 variable, and I am not familiar enough to understand what it wants. Same with arguments…is this the task script?

Your solution looks very helpful, so any guidance would be greatly appreciated. I’m definitely doing something wrong here… Thanks!

Hi Iamdamion,
first, here’s the help screen of the python script which describes the options

Hi Iamdamion,
first, here’s the help screen of the python script which describes the options

usage: PsychoPyPython.py [-h] [--version] [-v] [-r PSYCHOPY_ROOT] [-b] [-s]
                         [-p] [-w WORKING_DIR] [-e ENV_VAR ENV_VAR ENV_VAR] -a
                         ...

PsychoPy Python: run any cmd within PsychoPy environment (Feb 2016)

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  -v, --verbose         Be informative
  -r PSYCHOPY_ROOT, --psychopy-root PSYCHOPY_ROOT
                        PsychoPy application root directory
  -b, --no-bytecode     Set environment to not generate bytecode
  -s, --use-shell       Run in a shell
  -p, --prepend-interpreter
                        Prepend python interpreter to command arguments
  -w WORKING_DIR, --working-dir WORKING_DIR
                        Working directory
  -e ENV_VAR ENV_VAR ENV_VAR, --environment-var ENV_VAR ENV_VAR ENV_VAR
                        Set environment variable: -e <var name> <value>
                        <pb|pe|ps|pn>. This option maybe used multiple times:
                        pb = path prepend, pe = path postpend, ps = path set,
                        pn = not a path
  -a ..., --arguments ...
                        Arguments to pass to the python interpreter (all args
                        after this option are passed through)

======= [CASE A: you have a system python ]

So let’s see a simple example of usage

python PsychoPyPython.py -r /Applications/PsychoPy2-1.84.app//Contents/MacOS -p -b -a myExperiment.py

To run PsychoPyPython.py I’m using here the python interpreter installed on my Mac, so no the one embedded in PsychoPy, but I want my script to be run by the latter. Therefore, I need to tell my script where to find it, with the “-r” option. In my case:

-r /Applications/PsychoPy2.app//Contents/MacOS

The -e option is for setting extra environment variables visible from to PsychoPy python interpreter (and your experiment script) or change the value of
variables already defined in the current environment (which might be handy with variable holding system path values)

As documented the parameters are 3, or 6 if you want to set 2 variables or 9, for 3 variables etc.

-e var_name value (pb | pe | ps | pn)

Suppose you want to set a new variable EXPERIMENT_FLAG, then you will pass

-e EXPERIMENT_FLAG 3 pn

which correspond to EXPERIMENT_FLAG=3

If you want instead to update an environment variable which already exists like for example

PATH_TO_DATA_FILES=/path/to/current/data, then you can pass

-e PATH_TO_DATA_FILES ../../other/data pe

which will set PATH_TO_DATA_FILES to point to /path/to/other/data.
‘pe’ specifies to update by post pending the value to the existing.

Note that the changes to the already existing variables do not affect your current environment but only the one where PsychoPy will run.

======== [ CASE B: you can’t rely on a system python, you have only the one in PsychoPy ]

If you don’t have a system python installed then you can use a shell script which does more or less the same as PsychoPyPython.py:

#!/bin/bash
# The first parameter must be the psychopy root dir of the application.
# If it's equal to ? then it's the PSYCHOPY_ROOT env variable content, if defined,
# otherwise it's set by default to /Applications/PsychoPy2.app.
# All the following parameters are passed on to the python interpreter.

DEFAULT_PSYCHOPY_ROOT="/Applications/PsychoPy2.app"

if [ ${OSTYPE:0:6} != "darwin" ]; then
    echo "This script doesn't support other environment than OS X"

fi

function usage {
    echo "Description: pass on a list of arguments to the PsychoPy python interpreter"
    echo "Usage: $0 (-r <dir> | -f <filename> | -e) [-i <interpreter>] [...]"
    echo "       -r: specify PsychoPy application root dir"
    echo "       -f: specify a file whose first line is the PsychoPy app root dir"
    echo "       -e: read PsychoPy application root dir from PSYCHOPY_ROOT environment"
    echo "           variable, if defined, otherwise set it to ${DEFAULT_PSYCHOPY_ROOT}"
    echo "       -i: use python interpreter"
    exit 1
}

interpreter=""

if [ $# -lt 1 ]; then usage; fi

case $1 in
    -r)
        if [ $# -lt 2 ]; then usage; fi
        PSYCHOPY_ROOT="$2"
        shift 2
    ;;
    -f)
        if [ $# -lt 2 ]; then usage; fi
        read -r PSYCHOPY_ROOT<"$2"
        shift 2
    ;;
    -e)
        shift
    ;;
    *)
        usage
    ;;
esac

case $1 in
    -i)
        if [ $# -lt 2 ]; then usage; fi
        interpreter="$2"
        shift 2
    ;;
    *)
    ;;
esac

if [ -z "${PSYCHOPY_ROOT}" ]; then
    PSYCHOPY_ROOT=${DEFAULT_PSYCHOPY_ROOT}
fi

if [ -z "${interpreter}" ]; then
    interpreter="${PSYCHOPY_ROOT}/Contents/MacOS/python"
fi

PSYCHOPY_ROOT=${PSYCHOPY_ROOT//\\ / }
export LD_LIBRARY_PATH=`pwd`
export PYTHONPATH="${PSYCHOPY_ROOT}/Contents/Resources":${PYTHONPATH}
export RESOURCEPATH="${PSYCHOPY_ROOT}/Contents/Resources"
export PYTHONHOME="${PSYCHOPY_ROOT}/Contents/Resources"
export MATPLOTLIBDATA="${PSYCHOPY_ROOT}/Contents/Resources/mpl-data"
export PYTHONDONTWRITEBYTECODE="1"
export EXECUTABLEPATH="${PSYCHOPY_ROOT}/Contents/MacOS/PsychoPy2"
export ARGVZERO="${PSYCHOPY_ROOT}/Contents/MacOS/PsychoPy2"

echo "${interpreter}" "$debug" "$@"
${interpreter} ${@}

The script runs on OSX, on Linux it will with minor changes, but not on MS Windows. Here’s the help screen:

Usage: ./PsychoPyPython.sh (-r <dir> | -f <filename> | -e) [-i <interpreter>] [...]
       -r: specify PsychoPy application root dir
       -f: specify a file whose first line is the PsychoPy app root dir
       -e: read PsychoPy application root dir from PSYCHOPY_ROOT environment
           variable, if defined, otherwise set it to /Applications/PsychoPy2.app
       -i: use python interpreter

For example, to replicate the command in CASE A

./PsychoPyPython.sh -r /Applications/PsychoPy2-1.84.app/Contents/MacOS myExperiment.py

=======[ Final considerations ]

I wrote these scripts for older versions of PsychoPy. They work for sure for up to version 1.84.
You should check if they work for newer versions. I’m no more into PsychoPy as I changed job a while ago, sorry.

Hope this helps.
Cheers,
Luca

Thank you for this example, Luca. I did originally check the help info, but the usage of the env_var argument was what was the least obvious from the help alone (and my limited experience). This explanation was very clear and I understand what it’s doing now. Thank you! This really helped and I appreciate you taking the time to give examples and share this script.