Embedding IronPython in IronPythonThe PythonEngine
![]()
IntroductionThis 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. 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 EmbeddingThe very basic case, performs the following steps:
Things to note include:
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 GlobalsWe 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 OutputThis 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.
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.
Last edited Fri Feb 15 13:42:11 2008. Counter... |
|||
|
Blogads
Follow me on: Tech Jobs |