JMRI® is...
Information on writing scripts to control JMRI in more detail:
Python and Jython (General Info)
JMRI scripts are in Jython, a version of Python, a popular general-purpose computer language
JMRI tools for working with your layout:
Layout Automation
Use JMRI to automate parts of your layout and operations:
Supported Hardware
JMRI supports a wide range of DCC systems, command stations and protocols.
By the community of

JMRI Help:

Contents Index
Glossary FAQ

Donate to JMRI Donate to

JMRI's support for Python 3 is under development. We expect there to be changes before its production release in JMRI 5.

Since JMRI 4.99.2 Python 3 support is only available in JMRI test release 4.99.2 or later. Make sure to check the release notes of the JMRI version you're using!

This support is experimental; we may still encounter killer problems that we're not able to solve. Please feel free to experiment with it, but don't i.e. write scripts that are critical to your railroad's operation using Python 3.

Please note that Python 3 support is currently only available for macOS and Linux computers. Some of the components it requires are not year available for Windows. We'll update to use them and make Windows support available as soon as those components are updated.

Python 3 Introduction

Getting Started

JMRI's Python 3 support is provided, in part, by running on a GraalVM virtual machine instead of the usual Java Runtime Environment. The first step is to install a GraalVM on your computer.

To do that, follow the GraalVM install instructions to install a Java 11 version.

Once you do that and start JMRI, a "Python 3" choice should appear in the language selector in the Script Input Window, and the file choosers for running scripts should give you a similar choice.

Our convention is that Python 3 files use a .py3 extension.

Issues and differences from Jython (Python 2.7)

  • Scripts should start with
        import jmri as jmri
        import java
        exec( open("jython/jmri_bindings.py3").read() )
    The third line is the Py3 syntax to read and execute another script file. In this case, it reads and executes the file that defines a number of symbols like `THROWN``, `turnouts`, etc.
  • The syntax for getting a class reference has changed. The only place you're likely to see that is in InstanceManager calls. They become:
        manager = jmri.InstanceManager.getNullableDefault('jmri.MyManager')
    (note quotes). More generally, if you need access to a Java type object for other purposes, you can get it with
    but we've provided a new version of InstanceManager.getDefault and InstanceManager.getNullableDefault that takes the class name as a parameter to make those common operations simpler.
  • Print statements need to have their value enclosed in parentheses:
        print (123)
  • Constants are not inherited: You have to reference DigitalIO.ON, not Light.ON.
  • Unlike Jython, JMRI's Python 3 can address (almost) any of the Python libraries you have installed on your computer.
  • You can inherit a Python class from a Java class, i.e.
    class Automat(AbstractAutomaton) :
        def init(self) :
            print ("init in Python 3")
        def handle(self) :
            print ("handle in Python 3")
            return False
    but when you're doing that you can't add any additional methods to the new class. This might require rethinking how to connect Java class code to your own scripting code; we hope to have some recommendations soon.
  • There's a problem with the various wait calls in AbstractAutomaton, e.g. waitMsec(..) and similar, that can result in JMRI locking up. We don't currently have a workaround for this.
  • The "syntax error" message doesn't tell you where the error was found. This is a real pain.