While I understand that 3rd party scripts can be dropped into the user-lib/pylib folder, what is the proper way to import a more complex library that requires running ‘python setup.py install’, or is normally installed with a package manager? Do I first need to build it using a separate python installation and move the resulting files into pylib? Do I use the Distutils packaged with Ignition to build it using the python packaged with Ignition?
Specifically, I’m trying to get the install twilio (not the module, just the regular twilio python package) to support some legacy scripts. After downloading the source, I tried simply moving the twilio folder containing the scripts to user-lib/pylib on the gateway to no avail:
There’s actually a procedure you can use to use pip from within Jython to install packages, then link Ignition’s Jython lib to an-off-the-shelf Jython lib and use that…however, the article specifically calls out the twilio module as not working, because one of its dependencies, cffi, has C dependencies (IE, won’t work in Jython).
For posterity, here’s the procedure, copied verbatim from an internal document:
0) On the server, install Java 8 if you haven’t already.
Thank you very much for the response. Exactly what I needed. Bummer about the twilio C dependencies. Would the java twilio API suffer from the same issues? I’m hoping I can maybe import a precompiled .JAR instead.
No, the Java package should be fine, although if you’re already loading a JAR it’s not that much more work to just write a module that exposes some scripting functions.
Hi,
I tried to follow these instructions and I got the following error when I ran “jython -m ensurepip” to install pip and setuptools:
Exception in thread “main” java.lang.UnsatisfiedLinkError: Could not load library. Reasons: [no jansi in java.library.path, The system cannot find the path specified]
at org.fusesource.hawtjni.runtime.Library.doLoad(Library.java:182)
at org.fusesource.hawtjni.runtime.Library.load(Library.java:140)
at org.fusesource.jansi.internal.CLibrary.(CLibrary.java:42)
at org.fusesource.jansi.AnsiConsole.wrapOutputStream(AnsiConsole.java:48)
at org.fusesource.jansi.AnsiConsole.(AnsiConsole.java:38)
at org.python.jline.AnsiWindowsTerminal.detectAnsiSupport(AnsiWindowsTerminal.java:57)
at org.python.jline.AnsiWindowsTerminal.(AnsiWindowsTerminal.java:27)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.python.jline.TerminalFactory.getFlavor(TerminalFactory.java:211)
at org.python.jline.TerminalFactory.create(TerminalFactory.java:102)
at org.python.jline.TerminalFactory.get(TerminalFactory.java:186)
at org.python.jline.TerminalFactory.get(TerminalFactory.java:192)
at org.python.jline.console.ConsoleReader.(ConsoleReader.java:243)
at org.python.util.JLineConsole.install(JLineConsole.java:107)
at org.python.core.Py.installConsole(Py.java:1744)
at org.python.core.PySystemState.initConsole(PySystemState.java:1269)
at org.python.core.PySystemState.doInitialize(PySystemState.java:1119)
at org.python.core.PySystemState.initialize(PySystemState.java:1033)
at org.python.core.PySystemState.initialize(PySystemState.java:989)
at org.python.core.PySystemState.initialize(PySystemState.java:984)
at org.python.util.jython.run(jython.java:263)
at org.python.util.jython.main(jython.java:142)
Well, that’s a Jython problem, not an Ignition problem, but, it seems like the error is trying to tell you as much as it can. It looks like there’s some general bugs with jansi in Jython on Windows; there may not be much to do here other than investigate with Jython’s folks: https://bugs.jython.org/issue2427
Is this the same procedure when attempting the same from a Ignition 8.1.X system?(Currently looking at a 8.1.4, but you guys upgraded to java 11 for a bunch of stuff and I figured I would check)
These instructions were written against 8.0, which also runs Java 11, and work fine. The Java installation is just for Jython’s pip, nothing to do with your actual Ignition system. You could also run Java 11 and I doubt it would cause any problems.
I tried all these steps and I was able to successfully install the desired package to jython. One issue I am having is that when I try importing from the package I installed (literally 1st line of my .py script) I get the following error:
File “C:\jython2.7.1\Lib\site-packages\serial_ init _.py”, line 33, in
from serial.serialjava import Serial
File “C:\jython2.7.1\Lib\site-packages\serial\serialjava.py”, line 38, in
comm = detect_java_comm([
File “C:\jython2.7.1\Lib\site-packages\serial\serialjava.py”, line 32, in detect_java_comm
raise ImportError(“No Java Communications API implementation found”)
ImportError: No Java Communications API implementation found
Does this mean that Java does not have serial communications abilities? The package I want to use uses python’s pyserial package which I also installed.
I don’t think Java had ever included an implementation of the comm API. It’s very old and has always been BYO implementation because it’s just an API to program against.
Something called rxtx used to be a popular implementation but I don’t know if it works any more.
The simplest option would probably be to use system.util.execute to launch your Python script directly and examine the result.
Alternately, you could (purchase and) install the serial module for the appropriate scope (Vision client or gateway) and then adapt your script to use system.serial scripting functions - then everything is kept within Ignition and is somewhat more ‘portable’.
Oh, right - system.util.execute is a 'fire-and-forget', it doesn't give you access to standard output. Try adapting this:
from java.lang import ProcessBuilder, String
pb = ProcessBuilder([r"C:\Users\pgriffith\AppData\Local\Microsoft\WindowsApps\python3.exe", r"C:\Users\pgriffith\Downloads\test.py"])
process = pb.start()
output = String(process.getInputStream().readAllBytes())
print output
(Note: This blocks until the process completes waiting on the input stream. It may or may not ever complete, depending on what you're running, which could block a thread forever. Be careful).