Source code for psychopy.app
Back to top
# -*- coding: utf-8 -*-
# Part of the PsychoPy library
# Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2022 Open Science Tools Ltd.
# Distributed under the terms of the GNU General Public License (GPL).
"""Module for the PsychoPy GUI application.
__all__ = [
from .console import StdStreamDispatcher
from .frametracker import openFrames
# Handle to the PsychoPy GUI application instance. We need to have this mainly
# to allow the plugin system to access GUI to allow for changes after startup.
_psychopyApp = None
[docs]def startApp(showSplash=True, testMode=False, safeMode=False):
"""Start the PsychoPy GUI.
This function is idempotent, where additional calls after the app starts
will have no effect unless `quitApp()` was previously called. After this
function returns, you can get the handle to the created `PsychoPyApp`
instance by calling :func:`getAppInstance` (returns `None` otherwise).
Errors raised during initialization due to unhandled exceptions with respect
to the GUI application are usually fatal. You can examine
'last_app_load.log' inside the 'psychopy3' user directory (specified by
preference 'userPrefsDir') to see the traceback. After startup, unhandled
exceptions will appear in a special dialog box that shows the error
traceback and provides some means to recover their work. Regular logging
messages will appear in the log file or GUI. We use a separate error dialog
here is delineate errors occurring in the user's experiment scripts and
those of the application itself.
showSplash : bool
Show the splash screen on start.
testMode : bool
Must be `True` if creating an instance for unit testing.
safeMode : bool
Start PsychoPy in safe-mode. If `True`, the GUI application will launch
with without plugins and will use a default a configuration (planned
feature, not implemented yet).
if isAppStarted(): # do nothing it the app is already loaded
return # NOP
# Make sure logging is started before loading the bulk of the main
# application UI to catch as many errors as possible. After the app is
# loaded, messages are handled by the `StdStreamDispatcher` instance.
prefLogFilePath = None
if not testMode:
from psychopy.preferences import prefs
from psychopy.logging import console, DEBUG
# construct path to log file from preferences
userPrefsDir = prefs.paths['userPrefsDir']
prefLogFilePath = os.path.join(userPrefsDir, 'last_app_load.log')
lastRunLog = open(prefLogFilePath, 'w') # open the file for writing
# NOTE - messages and errors cropping up before this point will go to
# console, afterwards to 'last_app_load.log'.
sys.stderr = sys.stdout = lastRunLog # redirect output to file
# Create the application instance which starts loading it.
# If `testMode==True`, all messages and errors (i.e. exceptions) will log to
from psychopy.app._psychopyApp import PsychoPyApp
_psychopyApp = PsychoPyApp(
0, testMode=testMode, showSplash=showSplash)
# After the app is loaded, we hand off logging to the stream dispatcher
# using the provided log file path. The dispatcher will write out any log
# messages to the extant log file and any GUI windows to show them to the
# ensure no instance was created before this one
if StdStreamDispatcher.getInstance() is not None:
'`StdStreamDispatcher` instance initialized outside of `startApp`, '
'this is not permitted.')
stdDisp = StdStreamDispatcher(_psychopyApp, prefLogFilePath)
if not testMode:
# Setup redirection of errors to the error reporting dialog box. We
# don't want this in the test environment since the box will cause the
# app to stall on error.
from psychopy.app.errorDlg import exceptionCallback
# After this point, errors will appear in a dialog box. Messages will
# continue to be written to the dialog.
sys.excepthook = exceptionCallback
# Allow the UI to refresh itself. Don't do this during testing where the
# UI is exercised programmatically.
"""Quit the running PsychoPy application instance.
Will have no effect if `startApp()` has not been called previously.
if not isAppStarted():
if hasattr(_psychopyApp, 'quit'): # type check
# PsychoPyApp._called_from_test = False # reset
_psychopyApp = None
raise AttributeError('Object `_psychopyApp` has no attribute `quit`.')
"""Get a reference to the `PsychoPyApp` object.
This function will return `None` if PsychoPy has been imported as a library
or the app has not been fully realized.
PsychoPyApp or None
Handle to the application instance. Returns `None` if the app has not
been started yet or the PsychoPy is being used without a GUI.
Get the coder frame (if any)::
import psychopy.app as app
coder = app.getAppInstance().coder
return _psychopyApp # use a function here to protect the reference
"""Check if the GUI portion of PsychoPy is running.
`True` if the GUI is started else `False`.
return _psychopyApp is not None
"""Get the reference to one of PsychoPy's application frames. Returns `None`
if the specified frame has not been fully realized yet or PsychoPy is not in
frameName : str
Identifier for the frame to get a reference to. Valid names are
'coder', 'builder' or 'runner'.
object or None
Reference to the frame instance (i.e. `CoderFrame`, `BuilderFrame` or
`RunnerFrame`). `None` is returned if the frame has not been created or
the app is not running. May return a list if more than one window is
if not isAppStarted(): # PsychoPy is not in GUI mode
if frameName not in ('builder', 'coder', 'runner'):
raise ValueError('Invalid identifier specified as `frameName`.')
return getattr(_psychopyApp, frameName, None)
if __name__ == "__main__":