An obvious requirement for a Python editor is to run your Python code. For standard Python, Mu does this in two ways:
With the Python runner (press the “Run” button).
With the graphical debugger (click the “Debug” button).
For MicroPython based modes, the code is run on the attached embedded device and not directly by Mu. For example, saving your code on an Adafruit board restarts the device and Circuit Python evaluates your code.
Both the Python runner and grapical debugger were created with the financial support of the Raspberry Pi Foundation.
If you are creating a new standard Python mode for Mu, you should at least make available the Python runner (please see Modes in Mu for more information about how to do this).
Both methods of running Python code essentially work in the same way: they
fire up a new child process and connect its stdin, stdout, stderr to the
PythonProcessPane found in the
mu.interface.panes namespace so you’re
able to interact with it in a terminal like environment.
However, the Python runner starts immediately whereas the debugger has to set up a bunch of debug-related scaffolding, which makes it start slower. This is especially noticeable on the less powerful Raspberry Pi machine. Basically, if you just want to run your script, use the Python runner.
The essentials of the Python runner are in the afore mentioned
PythonProcessPane class. The
start_process method is used to create the
new child process. The resulting process becomes a
process attribute on the
instance of the
You have some control over how the child process behaves.
You should supply the
You must also provide a
working_directorywithin which the script will run (this is usually the user’s
interactiveflag (which defaults to
True) will mean the user will drop into a simple Python REPL when the script completes. The default is at the request of the Raspberry Pi Foundation who explain that it is often handy for beginner developers to run their script and then explore the resulting context interactively.
debuggerflag is set to
True(the default is
False) then the debug runner (see below) is started in a child process for the referenced script. This overrides the
interactiveflag to being
command_argsfor the referenced script should be a list of strings. The default is no
Handlers are configured to handle various events, such as when the process finishes or when a user type a character.
PythonProcessPane includes basic command history and input editing
features. It’ll also respond to CTRL-C and CTRL-D. Copy and paste can be
accessed via a context menu.
The graphical debugger exists to give beginner programmers an easy way to observe their code while it is running and allows you to use breakpoints, step over and into code as well as use a simple object inspector to view the status of objects in scope.
When a user clicks the “Debug” button Mu transitions to “debug” mode which exposes the functionality of the debugger client which, in turn, communicates with the debug runner process which is actually driving the user’s script.
The debugger is designed to be as simple as possible in order to introduce beginner programmers to the basic concepts of a debugger in the easiest way. It does NOT strive to be extensive or particularly powerful. Rather, its aim is to encourage beginner programmers to explore their code while it is running.
In this sense if conforms to the Mu outlook of providing the first steps for a beginner programmer with a view to them quickly graduating to a “proper” development environment once they’ve found their feet.
Most of the debugger’s functionality can be found in the
namespace. Coordination is done in the
The debug client exists within the Mu process. It spins up an instance of
mu.debugger.client.CommandBufferHandler class in a separate thread to
handle inter-process communication in a non-blocking manner, so the UI thread
is never blocked.
mu.debugger.client.Debugger class is used to react to incoming events
from, and as an API for Mu to issue commands to the debug runner. It uses a
reference to a
view object to update the user inteface as events are
The debug runner exists on a new child process and makes use of Python’s
bdb debugger framework. It
spins up a new thread to run the
command_buffer function that listens for
The most interesting aspects of the runner are found in the
mu.debugger.runner.Debugger class which inherits from the
found in Python’s standard library. It responds to commands from the client
and sends messages when various events occur during the debugging process.
These messages are picked up by the debug client and reflected in Mu’s UI.
mu.debugger.runner.run function is the entry point for the debug
runner and, as specified in Mu’s
setup.py, is accessed via the
command. This command expects at least one argument: the name of the script
to be debugged. Any further arguments are passed on to the script to be