Special Notes for macOS Users#

Although much progress has been made getting py5 to work on macOS, there are a few remaining issues and limitations. The issues that are fixable will be addressed in future py5 releases. The remaining issues are minor and in line with typical macOS experiences.

TL;DR

  • When using Jupyter Notebooks, start each notebook with the %gui osx magic

  • The run_sketch() method’s block parameter is by necessity set to False when run through Jupyter Notebooks and set to True when run through a generic Python interpreter

  • The py5bot Jupyter kernel and some py5 magics cannot use the OpenGL renderers

  • The render helper tools cannot use the OpenGL renderers

  • When using Jupyter notebooks, Sketches that use the default renderer will not appear as an icon on the dock at the bottom of the screen

  • When using Jupyter notebooks, the select methods select_folder(), select_input(), and select_output() will not work.

  • Ignore the warnings you see when exiting a Sketch (Issue #6)

None of these will stop you from using py5 productively on macOS.

Jupyter Notebooks#

Everything will work just fine after executing the following IPython magic at the start of each notebook:

%gui osx

This changes how Jupyter executes later notebook cells to allow GUI windows to open and be usable. Do this before importing py5. If you import py5 without doing this, py5 will run the magic for you after giving you a polite warning.

That magic command should not be run on non-macOS machines. If you need your notebook code to run on multiple platforms, use the following code instead:

import sys

if sys.platform == 'darwin':
        get_ipython().run_line_magic('gui', 'osx')

The %gui osx magic will enable macOS Cocoa event loop integration. Use of this magic is not unique to py5; it is also used for other Python applications that open interactive windows. It instructs Jupyter’s Python kernel to share the main thread with the window. On macOS, all GUIs are required to run on the main thread. The Python kernel, however, also needs to use the main thread to execute cells. Therefore, the main thread must be shared.

To see an example demonstrating the consequences of this sharing, try running the following Sketch on macOS:

import time


def setup():
    py5.size(200, 200, py5.P2D)


def draw():
    if py5.frame_count % 50 == 0:
        py5.println(py5.frame_count)
    py5.square(py5.random_int(py5.width), py5.random_int(py5.height), 10)


py5.run_sketch(block=False)

print('start pause')
time.sleep(3)
print('end pause')

When this code is run on a Linux or Windows computer, the output will be similar to this:

start pause
50
100
end pause
150
200
...

But when run on macOS, the output will be:

start pause
end pause
50
100
150
200
...

Also, you’ll notice the Sketch window does not open on the screen until after “end pause” is printed. This will be the case for the OpenGL renderers P2D and P3D as well as the default renderer JAVA2D.

Furthermore, if your Sketch uses the default renderer JAVA2D and you were to later execute time.sleep(3) in another notebook cell, you would momentarily see the Sketch stop animating. The Sketch actually is still running, but the new frames are not being drawn to the screen. For the above Sketch this will be apparent at the end of the 3 seconds when many new squares appear at the same time. The Sketch really is running normally during this time, but because of the shared main thread, the new frames are not being drawn to the screen. This behavior only applies to the JAVA2D renderer and not the OpenGL renderers P2D and P3D.

There are just a few more things macOS users need to know about using py5 in a Jupyter notebook.

Blocking#

In Jupyter, the run_sketch() method will never “block”, which means that the method will return right away and let you execute lines of code that appear after it or in other notebook cells. This shouldn’t be a problem for notebook users as this is most certainly what you would want to happen anyway. If you want some code to run right when the Sketch exits, implement an exiting() function, which will be called by py5 as the Sketch is shutting down.

If you need to simultaneously run multiple Sketches in the same process on macOS, running them through a Jupyter notebook (using class-mode) is your only option.

Select Methods#

When run through Jupyter, the select methods select_folder(), select_input(), and select_output() will not work. Consider using IPython widgets instead.

Dock Icon#

When run through Jupyter, Sketches that use the default JAVA2D renderer will not appear as an icon on the dock at the bottom of the screen. This does not apply to Sketches that use the OpenGL renderers or Sketches run through the generic Python interpreter.

py5bot and py5 magics#

On macOS, the Jupyter py5bot kernel and the py5 magic command %%py5bot cannot use the OpenGL (P2D and P3D) renderers. The %%py5draw magic also cannot use the OpenGL renderers, and the %%py5drawdxf magic is not available.

A future version of py5 will address these issues.

Generic Python Interpreter#

Starting with py5 version 0.7.2, a Sketch can run through the generic Python interpreter (outside of Jupyter). The limitations are that you can only run one Sketch at a time and that exiting the Sketch will terminate the Python process.

The run_sketch() command will always “block”, which means that the method will not return and allow you execute lines of code that appear after it. Since exiting the Sketch will also terminate the Python process, the call to run_sketch() will typically be the last line in your Python script.

Render Helper Tools#

The render helper tools @render(), render_frame(), @render_sequence(), and render_frame_sequence() cannot use the OpenGL (P2D and P3D) renderers.

A future version of py5 will address these issues.

Sketch Exit#

When the Sketch exits you will see the following warning:

NewtNSView::dealloc: softLock still hold @ dealloc!

Ignore that. Windows and Linux users also get odd messages when exiting a Sketch.