Embedding IronPython in IronPython

The PythonEngine

IronPython as a black box ?

 

 

Introduction

This article came about from a need to capture standard output from code being executed simultaneously in different places.

In the process we discovered that you could create, configure and call the heart of IronPython, the PythonEngine, from inside IronPython!

This is interesting for executing code in an isolated context [1]. You can also configure the PythonEngine in interesting ways, like setting an arbitrary stream as the standard output for the engine. Smile

If you are interested in embedding IronPython in a .NET application, then prototyping and experimenting from the interactive interpreter makes this a much more fun experience.

Note

This article covers IronPython 1. The IronPython Cookbook has a shorter recipe on experimenting with the IronPython 2 hosting API 2 from IronPython: IronPython 2 from IronPython.

Simple Embedding

The very basic case, performs the following steps:

  • Instantiate PythonEngine
  • Create a new module, with a dictionary of values (the global scope)
  • Set this as the default module
  • Execute a script

Things to note include:

  • No need to add a reference to the IronPython.Hosting assembly. Unsurprisingly, IronPython already has one. Smile
  • The boolean value means that our new module is published to sys.modules with the name we give it
  • The dictionary we pass in is just a standard 'python' dictionary. From the C# side this would have to be some object implementing IDictionary.

The result is that 'Hello World' is printed to the console.

from IronPython.Hosting import PythonEngine

py = PythonEngine()

values = {'string': 'Hello World'}

mod = py.CreateModule('__main__', values, True)
py.DefaultModule = mod

script = "print string"

py.Execute(script)

Module Globals

We could configure the values in our module in a slightly different way. Every module is an instance of EngineModule. This has a Globals property, which can be configured using the methods of IDictionary.

In this case we call CreateModule with a string and a boolean, and omit the values dictionary:

from IronPython.Hosting import PythonEngine

py = PythonEngine()


mod = py.CreateModule('__main__', True)
py.DefaultModule = mod
mod.Globals.Add('string', "Hello World")

script = "print string"

py.Execute(script)

Setting the Standard Output

This isn't really any more complicated, except we create a subclass of the abstract class Stream, and set it as the standard output for our engine :

from IronPython.Hosting import PythonEngine
from System.IO import Stream
from System.Text import Encoding

py = PythonEngine()

class Diverter(Stream):

    def __init__(self):
        self.string = ''

    def Write(self, bytes, offset, count):
        # Turn the byte-array back into a string
        self.string += Encoding.UTF8.GetString(bytes, offset, count)

    @property
    def CanRead(self):
        return False

    @property
    def CanSeek(self):
        return False

    @property
    def CanWrite(self):
        return True

    def Flush(self):
        pass

    def Close(self):
        pass

    @property
    def Position(self):
        return 0

output = Diverter()
py.SetStandardOutput(output)


values = {'string': 'Hello World'}

mod = py.CreateModule('__main__', values, True)
py.DefaultModule = mod

script = "print string"


py.Execute(script)

print 'Captured standard output: %s', output.string

(Thanks to Dino Viehland for setting me straight on this implementation.)

The great thing is, that on multi-core machines with separate engines running on separate threads you should get much better performance from IronPython than CPython. Embedding multiple interpreter is also something that CPython doesn't excel at. However, there are indications that in the long run this feature may not remain in IronPython, so perhaps it is better to not rely on it.

[1]To make it a real sandbox it would need to be a separate app-domain of course.

For buying techie books, science fiction, computer hardware or the latest gadgets: visit The Voidspace Amazon Store. If you're looking for a new techie job, try the Voidspace Tech Job Board. This is part of the Hidden Network of technology and programming jobs.

Hosted by Webfaction

Return to Top

Page rendered with rest2web the Site Builder

Last edited Fri Feb 15 13:42:11 2008.


Counter...


Voidspace: Cyberpunk, Technology, Fiction and More
Search this Site:
 
Web Site

IronPython in ActionIronPython in Action

Blogads

Follow me on:

Twitter

Pownce

Jaiku

Del.icio.us

Shared Feeds

Tech Jobs

Hidden Network

Tech Jobs Board

Hosting for an agile web