I would like to run Python script from my JSL code. What is the best way to do that? Thank you
Here's an example I was playing with
txt=runprogram(executable("python"),options({"C:\Users\User\Desktop\tweepy\twpy2.py"}),readfunction("text"));
Tweepy is a python package for twitter. This example expects the python program to start, produce output, and terminate, before the JSL continues. There are other ways to use RunProgram.
Update: Since JMP 14.0 (and much improved in 15.0), the best way to run Python from JSL is now to use the JMP interface implemented in the commands Python Init(), Python Submit(), etc.
More information here:
https://www.jmp.com/support/help/14-2/python-integration-functions.shtml
For a wrapper that supports running Anaconda virtual environments, check:
https://community.jmp.com/t5/JMP-Scripts/Anaconda-Environments-Integration/ta-p/221565
I'm struggling with the 'run program' command. The line below works fine from a command prompt:
c:\mycompany\anaconda3\python.exe "c:\users\myuserid\temp\pythonsqltest.py"
I'm trying to run it by executing this script:
Names Default To Here( 1 );
RP = RunProgram(
Executable( "c:\mycompany\anaconda3\python.EXE" ),
Options( {"c:\users\myuserid\temp\pythonsqltest.py"} ),
ReadFunction( Function( {this}, Write( this << read ) ) )
);
I'm thinking I don't really understand the role 'ReadFunction' plays here. What am I missing?
readFunction tells RunProgram how to deal with the output of your python program (the data written to stdout). If you supply an actual JSL function, compiled by the function function, as in your example, then JSL and python are running independently and whenever JMP is idle, your JSL function can be called to retrieve some more output from python. This might be useful if the python program runs forever and makes an infinite stream of output. The other example posted here uses readfunction("text"), which is a simple way to get back all of the output from the python program (which must terminate, of course). The output comes back as the result of the runProgram function.
If you supply a function for runProgram to call, then you must also keep the runprogram object in a JSL variable so the connection between JMP and Python isn't destroyed too soon: obj = runProgram(...)
The this parameter in the readFunction is the same as the obj variable above. It gives you access to the methods of the runProgram object, like <<read.
edit: And the output of the write function goes to the JMP log; be sure to look there for your results.
Use
txt = runprogram( ... readfunction("text"));
If the python program produces any stdout (print statement, etc) it will come back to JSL as the result of runProgram. JSL won't continue until the Python program terminates with readfunction("text"). You might want to print something like
filename.dat,100
so JSL can know there are 100 lines of data in that file. Or print an error message and handle that if the database is unavailable.
(JSL also has some SQL capabilities that might be more appropriate @Eric_Hill )
Might be simpler and faster to read data directly in to JMP using an ODBC driver. What's your SQL database? I have a lot of experience with Oracle and could help with that.
I'm using the ODBC drivers now and they are not reliable. I don't really think it's JMP but switching from JMP 12 - 13 and oracle 11-12 definitely upset the applecart. I know have to close and reopen the database connections about every five queries in order for things to run reliably.
I'm using Oracle's 64-bit ODBC driver for Oracle 11 to talk to an Oracle v12 database. I haven't seen any behavior like you mentioned. I've used this for JMP 11 and 12. We haven't transitioned fully to JMP 13 yet; v13.1.0 fixed a bug where V13.0 couldn't read a CLOB.
I could never get the Oracle ODBC driver from Microsoft to work btw.
Good luck!
x = RunProgram(
executable( "/path/anaconda/bin/python" ),
options( "/path/filename.py" ),
readfunction( "blob" )
);
Then to do the opposite, run JSL from a python script. This works on a Mac, JMP 13.2 (and this is python not jsl)
import os
os.system('open /Applications/JMP\ Pro\ 13.app/Contents/MacOS/JMP /path/script.jsl')
the open argument has the application path, one space and then the path/file to open.
Its probably imporant to have
//!
on the first row of the script so it will auto run. And then on the last line, include this
Quit();
This will close the instance of JMP that os.sytem started.