Scripting Functions Using ScriptManager - Printing/Logging

I'm writing some scripting functions using the ScriptManager class. I'm using it to create a ScriptFunction class, based on a string of Python code.

From what I can tell, it appears to work, but for whatever reason, I'm not able to see any prints in the Script Console. Although they show up in the Designer's console just fine.

I'm assuming that technically, the function works, but it's jarring to not be able to see anything about in the script console. Why would this be the case? I would guess it's related to scoping, and maybe with the Designer and Gateway Hook implementations.

And actually, for another function where a very large dataset is being returned, instead of the usual <PyDataset: 45120 rows> output, it's attempting to print the full dataset with every piece of data listed. Which just kills the designer.

What should I be looking out for, to get the logging and printing to behave like regular native Ignition functions, or functions written in the scripting library?

This is expected behavior - you'd get the exact same output if you had written that code yourself in the script console:

The script console is a bit of a one-off unicorn; it manually "wraps" the stdout and stderr buffers for code executing inside itself. Logging should be considered a "side channel" for information capture - if you want something to be visible to the caller, your options are to return it directly or write it to stdout (which itself has caveats for gateway scope). No free lunch, unfortunately.

1 Like

Thanks as always Paul :slight_smile:

A followup question though, nowhere in the function definition in the string, am I putting any log statements. So I might be missing something somewhere, but seems like the return value is always being printed in the 'Output Console'. This is fine, except for when a function is returning a potentially very large dataset. Here is an example where it's trying to print out the whole dataset, and freezing up.

Is there anyway I can control what gets printed out in this case?

So I've been trying to wrap my head around it a bit more. Running code in the script console, is always ran in the designer scope? So when I'm calling a function written in the scripting library, or even defined in the script console itself; what's the difference between that, and running a function written in a third party module?

Yes.

Third party modules must install jars and hook classes for each process scope they wish to support: gateway, client, and designer. A third party module may register java functions under python names in system.*, and run arbitrary jython code. In designer or client scopes, the jython code run from within the module will use that same scope, unconditionally. In gateway scope, the arbitrary code will run in the non-perspective project scope for the script manager selected. Typically, this would be non-project scope, with gateway scripting project resources, if any, available.

Third party modules can also install remote procedure call support, so that client and designer scopes can call out to gateway scope.

I've set up the DesignerHook (correctly I hope), and the function technically works just fine. The only difference in behavior I'm seeing so far, is where it decides to print things.

But you also mentioned installing jars, could you elaborate on that a bit more? Perhaps I'm missing something there.

Jars are inside your module file. Your module specifies in module.xml which jars get installed in which scopes, and which scopes have hook classes to invoke.

Got it, it seems like those are set up correctly too.

I did some experimenting just now, and it seems like it's something about the ScriptManager. I created a function that just runs pure Java, and it prints in the output buffer just fine. Also of note, it didn't print in the Output Console in the designer.

So back to the screenshot in the original post, it shows how I'm defining a function. I'd like to understand more about what's going on with the ScriptManager's compileFunction(), and ScriptFunction's .invoke(). What are the differences between that implementation, vs. just implementing it directly in Java code? I'm thinking there's some differences in scopes.

You are blazing a new trail, I think. I would not expect a script manager obtained in your module from the module context to be the same environment as for the caller of your registered script function. It might be in Vision Client scope, but I wouldn't bet on it.

And loggers don't ever output to the designer script console. And module code that prints to System.stdout or System.stderr should expect their output to only go to the debug console/wrapper log.

Pssst! What do you really need to do? You shouldn't be running predefined jython within your java module, I wouldn't think.

2 Likes