An Advanced Primer — Python, Libraries, Versions, and the Future
Background
Ignition provides users with the ability to do Python scripting as a core part of the Ignition platform. Ignition and Ignition Edge (with Compute) both provide the environment for advanced scripting and most Ignition customers use Python in their projects in some manner.
What’s available out-of-the-box?
Ignition includes Python by using a well-respected project called Jython, which is used in other products as well, like IBM Websphere. Jython’s current release is Jython 2.7 and includes most of the Python Standard Library. Inductive Automation has created a rich scripting API with well over 300 script functions with documentation and examples. In addition, Jython has a unique ability to import Java classes, which makes all classes in the Java Class Library available, along with a large variety of other Java libraries that are included in the Ignition platform.
What is Python, and what are CPython and Jython?
Python is a language specification. If you learn the Python programming language, and you write some Python code, you then need somewhere to run your Python code.
CPython is a program (“interpreter”) that you can run to execute your Python code. It’s written in C, hence the name “CPython.” Unfortunately, CPython is normally referred to as “Python,” as it was the first interpreter written, and in fact, when you “download Python” from python.org, it gives you CPython. Online articles talking about “Python” may be talking about the Python language or the CPython interpreter, and you have to think through how “Python” is used in any given sentence to know which one the author means.
Jython is another interpreter that can execute your Python code. It’s written in Java, which enables it to access the Java class library and to easily run cross-platform. Ignition’s Jython implementation makes it simple and performant to access Ignition’s systems through Ignition’s scripting API.
Why does Ignition use Python 2.7? Isn’t 2.7 no longer supported?
CPython 2.7 has been retired. You can find more information about that here: Sunsetting CPython. For a good part of that page, these folks are specifically talking about the CPython interpreter.
Jython 2.7 is still under development and continues to have new versions and bug fixes released. Inductive Automation also maintains our codebase of Jython and occasionally applies bug fixes as well as the need arises. This means that Ignition’s Python 2.7 is still supported and will continue to be in the future. CPython’s sunsetting doesn’t affect Ignition.
Jython 3 is the next major release of Jython, but it isn’t available for public release yet and is likely a few years away from release. Python 3 is also a different language from Python 2, as the Python language has some changes that require adjustments/rewrites of Python 2 code to run in Python 3. For that reason, Inductive Automation currently expects that Ignition will continue to support Python 2 going into the future, even after Jython 3 is released. It’s possible Ignition will support Python 2 and Python 3 simultaneously at some point in the future.
What about Python libraries?
Python libraries (most of which can be found at pypi.org) are a mixture of Python code and C code. Because CPython is based on C, the CPython interpreter is written to be able to access native C libraries.
Because Ignition’s Python interpreter is Jython, that means unlike CPython, Java libraries are accessible. It also means C libraries aren’t accessible.
Libraries written in pure Python are generally available in Jython. Since the majority of the most popular Python libraries do require C libraries, the selection of Python libraries that can be used in Ignition directly is fairly limited. For example, numpi, scipi, pandas, and scikit-learn are all unavailable. However, libraries intended for the web and other less data-intensive applications sometimes work. Requests is a good example of a versatile REST library that you can import into Ignition.
If you want to import libraries, drop them into Ignition’s user-lib/pylib folder. They’ll be automatically accessible on the Gateway and also automatically distributed to any open clients.
If you want to use pip, you can use the Jython Standalone Installer to install a local copy of Jython, install packages with pip (‘jython -m ensurepip’, then, ‘jython -m pip install <package>’), and then copy those installed packages from your local Jython installation’s site-packages/ folder to Ignition’s user-lib/pylib/site-packages. As noted, most Python packages won’t work with Jython since they have C dependencies, but a number of them do, so feel free to give this a shot if desired.
Can I run Python 3 code from Ignition?
Sure, you can invoke code written for Python 3 from inside Ignition. You can’t run that code directly inside Ignition, so Ignition’s scripting API wouldn’t be available, and your Python 3 code won’t be saved with any standard Ignition Gateway Backups, but we have plenty of customers who are doing machine learning, advanced data analytics, and other functions in Python 3 code that runs alongside Ignition.
There are two ways to do this.
Approach 1
The cleanest approach is to wrap your Python 3 code with Flask or Bottle, which makes it available by a simple REST call from Ignition.
A simple Bottle example:
from bottle import route, run
@route('/hello')
def hello():
return "Hello World!"
run(host='localhost', port=8080, debug=True)
In Ignition:
result = system.util.httpClient().get(“http://localhost:8080/hello”)
After doing that, you’ll need to set up your Python program as a service on the OS you’re running. There are many guides available online for this step. (In Windows, you can use Python’s pywin32 library. On Linux, this can be done by creating a service for systemd.)
Approach 2
Another approach is to invoke the Python script directly from Ignition. This is less portable and scalable, and doesn’t provide a strong separation between your Python 3 program and Ignition, but it is simpler to configure and avoids the need to run an additional service.
Keep in mind that going this direction may not return information on Exceptions or errors like Flask or Bottle will provide, unless you specifically write your invocation to process them. You’re also limited to send around 32kB of string characters in the arguments in Windows, and the limit varies on Linux and macOS.
import subprocess
result = subprocess.check_output(“/path/to/executable/python3”, “/path/to/python/program.py”)
How can I include Java libraries?
Including external Java libraries that can be accessed from Python is a great way to extend functionality. Writing a simple module and exposing scripting functions is fairly easy to do. Before doing this, we recommend at least having an Inductive University credential and having some Java experience.
Module Development Quick Start
Adding Libraries to your Modules
Note that Module Development is done in Java, and isn’t an activity that Inductive Automation’s tech support directly supports. The SDK Documentation can be very useful, and if you’re already versed in Java and have done some troubleshooting on your own first and are still having issues, the Inductive Automation Module Development Forum can sometimes provide assistance as well.