IronPython is an implementation of Python for .NET. It provides full access to .NET libraries through the Python programming language, while also providing access to standard Python libraries. While it can be used to write standalone applications, this article is about using it as a scripting language for your application.
Why a Scripting Language?
- Change functionality at run time
There could be lots of reasons for this - maybe every one of your customers want your application to behave differently and writing and shipping plugins is too much work. Or your customers are developers and they want the ability to change how the app behaves and customize it with immediate feedback, without having to recompile the app or plugins. Or, you are testing some functionality and want the application to behave differently at different times, without breaking into a debugger.
- Provide "extra' functionality
You're running your application and you notice that it's eating up memory. You decide to run it through a memory profiler, but before that, you want to run a full GC so that the profiler only picks up live objects. Wouldn't it be great if there was some way to call
GC.Collect? Or let's say you have a complicated UI that requires a lot of navigation and you want to spare developers the trouble of going through the UI every single time. Wouldn't it be nice to have something that would automatically do whatever is necessary and help developers get to the interesting part quickly?
- Live testing
Unit testing is great for testing out individual components separately, but wouldn't it be nice to have the ability to write tests that could run on a live system? Like say, when the user clicks button X and the software is in state Y, run test Z? Or do UI testing like filling out textboxes and clicking buttons automatically?
- Poking around live systems
When you are stuck without a debugger and want to check the state of the system (like the value of a class member, for example), wouldn't it be great to have the ability to just type that into a command window and see the result right away?
IronPython is incredibly easy to integrate. You'll need to:
- Add a reference to IronPython.dll from your application
- Instantiate a
- Add the objects that you want to expose via scripting to
- Redirect standard output and error streams so you can show errors and script output
The following snippet of code shows how it has been done in the attached sample application:
private void InitializeIronPython()
Options.PrivateBinding = true;
pythonEngine = new PythonEngine();
MessageBoxStream s = new MessageBoxStream();
MessageBoxStream is a class deriving from
System.IO.Stream that shows whatever is written to the stream using
pythonEngine.Globals.Add method exposes your objects as global variables to the scripts. The first parameter is a
string that translates to the variable name in the script, and the second parameter is the object corresponding to that variable. The sample application exposes the
Form object and a business logic object to the script.
The sample application also has a "command prompt" at the bottom, which is actually a
textbox, to execute live Python code. This is how that code looks like:
private void commandPrompt_KeyPress(object sender, KeyPressEventArgs e)
if (e.KeyChar == '\r')
It simply forwards the text to the
ExecuteToConsole method on the
The attached project demonstrates how to do things mentioned in the previous section. It's a pretty contrived application - it has two input
textboxes and an output
textbox. There are three buttons, "Add", "Subtract" and "Custom". As you would expect, the Add button adds the numbers in the input
textboxes and writes it to the output, Subtract subtracts them and Custom allows people to write custom actions. Let's go through the points mentioned in the previous section and see how they can be done using IronPython.
Change Functionality at Run Time
The "Custom" button executes a script named custom.py in the application's directory. That script gets the input
textboxes and a reference to the
Form instance, which it can use to do whatever custom action it wants. IronPython allows you to control what objects the script can reference.
private void customButton_Click(object sender, EventArgs e)
Dictionary<string,object /> locals = new Dictionary<string,object />()
pythonEngine.ExecuteFile("custom.py", pythonEngine.DefaultModule, locals);
The custom.py script automatically gets the global objects added to the
pythonEngine object. In addition to them, you can pass a dictionary of name/object pairs as local variables for that script. The script file can then access them like:
def append(x, y):
This script simply concatenates the text in the input
textboxes, converts the concatenated result to a number and calls the
As another example, type the following command:
form.TransformResult = lambda x : '-'.join(str(x))
Then do an Add or Subtract - you'll notice that the result has hyphens between the digits.
If you look at the code for
ShowResult, you'll see that it calls the
TransformResult delegate (if available) before setting the
Text property. The above snippet of code creates an anonymous function that converts the passed number to a
string and then inserts a hyphen between each character. That anonymous function is assigned to the
TransformResult delegate of the
Form object, which it then invoked when you clicked the Add Button.
Provide "Extra" Functionality
You can simply type
GC.Collect in the command prompt
textbox and hit Enter and have the CLR do a GC right away.
For a more interesting example, let's say that you as a developer would like to know the results generated in the current session. Assume that this is something that you wouldn't want to write as part of the application. With IronPython, you could do something like:
resultTextBox = form.Controls.Find('result', True)
results = 
def fn(arg1, arg2) : results.append(resultTextBox.Text)
resultTextBox.TextChanged += fn
You could then type...
... at any point in the command prompt to get the results calculated so far. The script basically subscribes to the
TextChanged event of
resultTextBox and appends the contents to a list.
Controls.Find method shown in the previous section, you can get a reference to any UI object and then manipulate it.
input1TextBox = form.Controls.Find('input1', True)
input2TextBox = form.Controls.Find('input2', True)
resultTextBox = form.Controls.Find('result', True)
input1TextBox.Text = '1'
input2TextBox.Text = '2'
addButton = form.Controls.Find('addButton', True)
print int(resultTextBox.Text) == 3
print int(resultTextBox.Text) == 4
As you can see, this piece of code gets references to the UI objects, sets values, executes an action and then verifies the result. You could also choose to expose the UI objects by adding them to
PythonEngine.Globals, instead of using
Control.Find to get them.
Poking Around Live Systems
You have already seen that you can access UI objects and manipulate them. You can do...
form.Text = 'IronPython'
... to change the
form's title, for example. You can also access business logic components, if you added them to the PythonEngine. The sample application exposes the
BusinessLogic object it holds with the name
bl, so you can now access its state too. It holds the last operation's type as a member, so you can do...
... to view the last executed operation.
I hope this article got you interested in IronPython and integrating scripting into your application. The IronPython project is hosted at CodePlex, so that's the place to go to download and learn more about it. The command prompt in the sample application is very rudimentary and there are alternatives like IronTextBox that do a much better job. You could also add "meta" commands to your prompt that allow you to execute arbitrary python files. And please keep in mind that the attached application is a sample application, intended to demonstrate IronPython integration, so if the code is missing error checking, you know why.
- 3:39 PM 3/16/2008: Initial post