Table of Contents

What is Jython?1

Jython is a Java implementation of Python that combines expressive power with clarity. Jython is freely available for both commercial and non-commercial use and is distributed with source code under the PSF License v2. Jython is complementary to Java and is especially suited for the following tasks:

  • Embedded scripting - Java programmers can add the Jython libraries to their system to allow end users to write simple or complicated scripts that add functionality to the application.
  • Interactive experimentation - Jython provides an interactive interpreter that can be used to interact with Java packages or with running Java applications. This allows programmers to experiment and debug any Java system using Jython.
  • Rapid application development - Python programs are typically 2-10x shorter than the equivalent Java program. This translates directly to increased programmer productivity. The seamless interaction between Python and Java allows developers to freely mix the two languages both during development and in shipping products.

Why do I use Jython?

That’s a good question, and the answer is because at work I am one of the developers for SCADA applications using the Ignition platform.

Where is scripting used?2

[J]ython is used in many places in Ignition. Each location has its own events that trigger your scripts to run, and add functionality to your projects in different ways.

Jython within Ignition

Ignition 8.0.16 (the latest stable version as of the date of this post) ships with Jython 2.7.1, and Zulu11.39+16-SA (build 11.0.7+10-LTS). All of this means that we have access to both worlds; Python 2.7, and Java 11.

And we are able to define the following function:

from javax.swing import JOptionPane

def warning(message, title='Warning'):
    """Displays a message to the user in a warning style popup dialog.

    Args:
        message (str): The message to display in an warning box.
        title (str): A title for the warning box. Optional.
    """
    JOptionPane.showMessageDialog(
        None,
        message,
        title,
        JOptionPane.WARNING_MESSAGE
    )

And when we call it like this:

warning('This one is a warning.')

We get the following:

jython-warning

Installing Jython on macOS

Do not install Jython 2.7.2 as it is not currently supported by PyCharm. See PY-44759.

Since I intend to set up Jython as a Project Interpreter in PyCharm, and considering the versions used by Ignition, I’ll download the following:

Updated: 2021-01-28

  1. Java 11
    1. Via Homebrew.
     brew install --cask zulu11
    
    1. Or from Azul for macOS (.zip, .dmg, .tar.gz).
  2. Jython 2.7.1
    1. Via Homebrew. Just tap coatl-dev’s Homebrew tap, and install jython@2.7.1:
     brew install coatl-dev/coatl-dev/jython@2.7.1
    

    Or

     brew tap coatl-dev/coatl-dev
     brew install jython@2.7.1
    
    1. Or by downloading the installer Jython Installer v2.7.1

I decided to install both using brew.

First zulu11:

$ brew install --cask zulu11
==> Downloading https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-macosx_x64.dmg
######################################################################## 100.0%
==> Installing Cask zulu11
==> Running installer for zulu11; your password may be necessary.
Package installers may write to any location; options such as `--appdir` are ignored.
Password:
installer: Package name is Zulu 11.45+27
installer: Upgrading at base path /
installer: The upgrade was successful.
🍺  zulu11 was successfully installed!

Then jython@2.7.1:

$ brew install coatl-dev/coatl-dev/jython@2.7.1
==> Installing jython@2.7.1 from coatl-dev/coatl-dev
==> Downloading https://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.1/jython-installer-2.7.1
==> Downloading from https://repo1.maven.org/maven2/org/python/jython-installer/2.7.1/jython-installer-2.7.1.jar
######################################################################## 100.0%
==> java -jar /Users/cesarcoatl/Library/Caches/Homebrew/downloads/558a886fedd7c18b1e12419bd4ab398b3ad7aaa902df4f5686ef3b695b89f2b9--jython-installer-2.7.1.jar -s -d /usr/local/Cellar/jython@2.7.1/2.7.1/libexec
🍺  /usr/local/Cellar/jython@2.7.1/2.7.1: 3,785 files, 148.7MB, built in 1 minute 22 seconds

NOTE: There is a warning when running jython with Java 11, but everything works fine.

$ jython
WARNING: An illegal reflective access operation has occurred
Illegal reflective access by org.python.core.PySystemState (file:/usr/local/Cellar/jython@2.7.1/2.7.1/libexec/jython.jar) to method java.io.Console.encoding()
WARNING: Please consider reporting this to the maintainers of org.python.core.PySystemState
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (Azul Systems, Inc.)] on java11.0.7

To circumvent this, you must run Jython with the following flags:

$ jython -J--add-opens=java.base/java.io=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.nio=ALL-UNNAMED -J--add-opens=java.base/sun.nio.ch=ALL-UNNAMED -J--add-opens=java.desktop/sun.awt=ALL-UNNAMED -J--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED
Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (Azul Systems, Inc.)] on java11.0.7
Type "help", "copyright", "credits" or "license" for more information.
>>>

Configuring Jython in PyCharm

  1. Open or create a project
  2. Open Preferences (⌘+,)
  3. Navigate to Preferences > Project > Project Interpreter
  4. Click on the gear icon and select Add…
  5. Choose System Intepreter
  6. Select /usr/local/bin/jython from the Interpreter list, and click OK
  7. PyCharm will name it Jython 2.7 by default, but you can change it
  8. Finally go to Preferences > Build, Execution, Deployment > Console > Python Console and add the following flags as Interpreter options

     -J--add-opens=java.base/java.io=ALL-UNNAMED
     -J--add-opens=java.base/java.lang=ALL-UNNAMED
     -J--add-opens=java.base/java.nio=ALL-UNNAMED
     -J--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
     -J--add-opens=java.desktop/sun.awt=ALL-UNNAMED
     -J--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED
    

To test it I will be using the jython branch of my Ignition project.

And when I run the Python Console I can do the following:

>>> from java.util import Date
>>> now = Date()
>>> print now
Thu Oct 01 19:01:27 PDT 2020
>>> print type(now)
<type 'java.util.Date'>

And just like the example in Jython within Ignition, I get the same pop-up by running the following code:

>>> import system.gui
>>> system.gui.warningBox('This one is a warning.')

jython-warning

Conclusion

And with that, my friends, you are all set.

Thanks, for reading.

Sources

  1. Jython - link 

  2. Ignition User Manual 8.0 - link