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.