The Five py5 Modes

The Five py5 Modes#

The py5 library is similar to Processing and p5 in that the basic functionality comes from user implemented settings, setup, and draw methods. These methods will initialize the Sketch parameters, run one-time setup code, and draw each frame of your animation.

In addition, py5 supports keyboard and mouse events with methods like mouse_clicked and key_pressed.

All of this is analogous to what users familiar with Processing and p5 might expect.

The py5 library has five “modes” that you can use to code these methods and write Sketches. Four of them are called Module Mode, Class Mode, Imported Mode, and Static Mode. They are documented on this page.

The fifth mode, Processing Mode, is a special mode enabling Processing (Java) users to make calls to Python, using py5 as a bridge to link Processing to Python. Processing Mode is documented separately.

Important

There are some known issues using py5 on Mac computers. The best option for Mac users is to use py5 through Jupyter Notebooks, and after using the %gui osx magic. See Special Notes for macOS Users for more information.

Module Mode#

Module Mode lets you write standalone settings, setup, and draw methods. Technically none are required but generally you will use both setup and draw.

In Module Mode, you will access py5 functionality through module-level functions and fields.

Below is a simple example:

import py5

def setup():
    py5.size(300, 200)
    py5.rect_mode(py5.CENTER)

def draw():
    py5.rect(py5.mouse_x, py5.mouse_y, 10, 10)

py5.run_sketch()

This will create a small Sketch that draws rectangles at the current mouse position.

Let’s explain each part of the code.

The first statement imports the py5 library in the same way that you would import any other Python library.

import py5

Next, the setup function. This function will be called one single time before beginning to repeatedly call the draw function for each frame of the animation. Typically the setup function is used to initialize variables or set py5 drawing options.

In this example the window size is set to be 300 pixels wide and 200 pixels tall. Almost always you’ll begin a setup function similar to this one. Notice the call to the size() function has a “py5.” prefix. All of the py5 methods and fields are module level attributes.

The call to rect_mode() configures drawing options for future calls to py5’s rect() method. By default the first two coordinates specify the shape’s upper left hand corner, but in this example they will specify the shape’s center.

Folks who are familiar with Processing will note that the call to size() is in the setup function, but technically it belongs in a settings function instead. Py5 allows the settings and setup functions to be combined, provided the rightful contents of settings appear before any of the real setup function code. There are rules about how combining settings and setup works; see run_sketch() for more information. If for some reason you cannot meet the requirements for this functionality, you will need to write a separate settings function yourself.

def setup():
    py5.size(300, 200)
    py5.rect_mode(py5.CENTER)

If the draw function is not found, the Sketch will display a static image using draw commands found in the setup function. If the draw function is found, it will be repeatedly called once for each frame of an animation.

In this example, we draw one 10 by 10 pixel rectangle centered at the current mouse position. Accessing the module variables mouse_x and mouse_y will always provide the mouse’s x and y coordinates.

def draw():
    py5.rect(py5.mouse_x, py5.mouse_y, 10, 10)

Finally, the call to run_sketch(). This is will open a window and display your animation.

py5.run_sketch()

Note by default the call to run_sketch() will not return until the Sketch exits, unless if it is running from a Jupyter Notebook or the IPython console. In that case it will return right away so the user can continue working in other cells in the notebook. Read the run_sketch() documentation to learn more.

The design of Module Mode is modeled after matplotlib’s pyplot.

Caution

Do not use wildcard import syntax with the py5 library:

from py5 import *

Doing so would import usable methods, but the fields, such as mouse_x and mouse_y in the example above, would not work correctly. This is because py5’s Module Mode is dependent on the module __getattr__ and __dir__ functionality described in PEP 562.

Wildcard imports also conflict with Python best practices (PEP 8) and in general should not be used.

If you don’t like prefixing everything with “py5.”, use Imported Mode instead.

Side Note

Combining settings and setup functions requires py5 to have access to the function source code via Python’s builtin inspect library. If you are running py5 code out of a Jupyter Notebook or a python souce file, it should work correctly. If you happen to be manually typing code into the generic Python REPL, it won’t work.

One More Side Note

Much like you would do for a Processing Sketch, you may want to put supporting materials in a data subdirectory. A py5 Sketch will look for this relative to the current working directory. You can find out what the current working directory is and change it with Python’s builtinos library.

>>> import os
>>> os.chdir('/dir/that/contains/your/data/subdir')
>>> print(os.getcwd())
/dir/that/contains/your/data/subdir

If that doesn’t meet your needs, you can also set it explicitly when you call run_sketch().

py5.run_sketch(py5_options=['--sketch-path=/dir/that/contains/your/data/subdir'])

Class Mode#

Class mode lets you create a class with its own settings, setup, and draw methods. The example above coded in Class Mode is as follows:

from py5 import Sketch


class TestSketch(Sketch):

    def settings(self):
        self.size(300, 200)

    def setup(self):
        self.rect_mode(self.CENTER)

    def draw(self):
        self.rect(self.mouse_x, self.mouse_y, 10, 10)


test = TestSketch()
test.run_sketch()

Let us again explain each part of the code.

The first line imports the Sketch class, which will provide the py5 functionality.

from py5 import Sketch

Next, define a new class that inherits from Sketch.

class TestSketch(Sketch):

Each of the settings, setup, and draw methods have a self parameter, just as they would in any Python class. The self parameter is used to access the py5 methods and fields provided by the parent Sketch class. Observe that every occurance of the “py5.” prefix in the Module Mode example has been replaced with “self.”.

Class Mode does not support combining settings and setup functions.

def settings(self):
    self.size(300, 200)

def setup(self):
    self.rect_mode(self.CENTER)

def draw(self):
    self.rect(self.mouse_x, self.mouse_y, 10, 10)

Finally, create an instance of the new class and call run_sketch().

test = TestSketch()
test.run_sketch()

As before, the call to run_sketch() will not return until the Sketch exits, unless if it is running from a Jupyter Notebook or the IPython console.

When developing in Jupyter Notebooks, Module Mode is the more convenient choice.

Class mode will let you run multiple Sketches at the same time. This cannot be done in Module Mode or Imported Mode.

Caution

When learning to use py5, you may accidentally conflate Module Mode and Class Mode by writing code like this:

def draw(self):
    self.rect(py5.mouse_x, py5.mouse_y, 10, 10)

Do you see the mistake?

The py5.mouse_x and py5.mouse_y code is suitable for Module Mode, so it is referencing the mouse position in a special default Sketch object found in the py5 module. However, in Class Mode you will create your own Sketch object, and as is being done here, call your Sketch object’s rect method. This code is accidentally mixing one Sketch’s methods with another’s fields. This is most certainly not what is intended, and any error message will not properly explain what is wrong.

This mistake will frequently be made when translating py5 code from one mode to another. I make this mistake all the time.

A good way to avoid this is to import the library with only one of “import py5” or “from py5 import Sketch”, depending on which mode you want to use. Using both import statements is asking for trouble.

Imported Mode#

Imported Mode was originally designed to be used by beginner programmers. It is analogous the Processing code users write in the Processing Development Editor (PDE). The Processing Editor does not currently support py5, but perhaps one day it will. Until then, you can use the py5 Jupyter Notebook Kernel or the py5-run-sketch command line tool.

Below is our example Sketch written in Imported Mode:

def setup():
    size(300, 200)
    rect_mode(CENTER)

def draw():
    rect(mouse_x, mouse_y, 10, 10)

# this is only needed to run the Sketch in Jupyter Notebooks; see note below
run_sketch()

Observe that any “py5.” and “self.” prefixes are removed. There are no “import py5” or “from py5 import *” statements.

Imported Mode does not let you define functions or variables with names that are identical to py5’s functions or variables. For example, you cannot create a variable named size or a function named rect(). These are considered “reserved” words. This is to protect you from writing code that redefines py5’s functions and variables and potentially creating hard to debug errors for you to fix. However, g, the main Py5Graphics object (g), is an exception to this rule because a single character reserved word would be confusing and because the variables r, g, and b are so commonly used for color values.

To run the Imported Mode code, make sure you have installed the py5 Jupyter Notebook Kernel, as described on the Install py5 page. Then start Jupyter Lab using this command:

$ jupyter lab

You will see the py5 kernel presented as an option in the Launcher. Click on it and put the code in a notebook cell.

The Python editor Thonny can be configured to work well with py5 in Imported Mode. See @tabreturn’s detailed blog post Portable Thonny and py5 for more information.

Running the Sketch

The run_sketch() method launches the Sketch and must be called when using Jupyter Notebooks. However, when using the py5-run-sketch command line tool or the Python editor Thonny that has been configured to use py5 in Imported Mode, run_sketch() should be omitted, as it will be executed on behalf of the user.

The operation of Imported Mode should work just as well as analogous code written in the other py5 modes.

As of release 0.9.1, py5 supports writing importable Python libraries written in Imported Mode. To enable this feature, you must add a specific identifying string to your Python library to flag it for special import processing. Refer to Importing Imported Mode Code for more information.

Static Mode#

Static Mode lets you create static images using functionless code. It is designed for beginner programmers who are making their first steps into Python programming.

The below Static Mode code will create a 300 by 200 pixel image with a gray background and 20 randomly positioned squares:

size(300, 200)
rect_mode(CENTER)
for _ in range(20):
    rect(random_int(width), random_int(height), 10, 10)

To use static mode, install py5bot as described on the Install py5 page. Then start Jupyter Lab using this command:

$ jupyter lab

You will see the py5bot presented as an option in the Launcher. Click on it and put the code in a notebook cell.

You can also program in Static Mode using the py5-run-sketch command line tool, or better yet, using Thonny. See @tabreturn’s detailed blog post Portable Thonny and py5 for information about how to set that up.