Ramblings of General Geekery

Exposing global variables in IronPython

Lately I’ve been playing around a bit with IronPython and how to embed it inside an application to add scripting features. I’m still figuring things out, but I had a hard time exposing global variables to the Python environment.

The idea was to expose a couple of .NET objects (mainly a few important managers/singletons from the app’s API) as global variables so that scripts could access and act on the important parts of the app (query the database, batch run actions, etc.).

At first, I exposed some objects as variables of my ScriptScope:

public void SetupScope(ScriptScope scope)
{
    scope.SetVariable("test_string", "This is a test string");
    scope.SetVariable("test_callback_method", new Action(TestCallbackMethod));
    scope.SetVariable("test_callback_function", new Func<string, string>(TestCallbackFunction));
}

The problem was that only interactive scripting would get access to those variables (I had a simple UI for typing commands to be executed on that ScriptScope). Using “test_string” in a function loaded from a module would result in a “name ‘test_string’ is not defined” error. Using either “import” or “global” would not fix it.

I then discovered the ScriptRuntime.Globals property, and tried to add something there instead.

public void SetupGlobals(ScriptEngine engine)
{
    engine.Runtime.Globals.SetVariable("test_global", "This is a test global variable.");
}

This didn’t quite work either, and was actually a step backwards: now I couldn’t even access this “test_global” variable from the interactive command line!

That’s until I tried the following:

import test_global

Now I could access my global variable! And using that import statement from my modules also successfully imported it into their scope. Yay!

I’m not quite sure why the import statement is working, and why the other things didn’t, but I’m a Python newbie so it’s not surprising. Reading the Python documentation, though, tells me “import” is used to import packages, not variables, so it remains a mystery to me… but at least, it works on my machine for now!