I’ve heard plenty of times on the IronPython Mailing List that embedding IronPython in Silverlight is easy at first, but then you fall off a cliff when trying to import, be it from a .NET namespace, the Python built-ins, or even other Python files. Let me clear some things up, and fix some code in the process.

Slight detour – Embedding in Silverlight 101

First off, Michael Foord has an article on his website about Embedding IronPython in Silverlight, which still works. However, that’s a ton of complicated code, all having to do with creating a ScriptRuntime instance correctly configured for Silverlight. To make this much less verbose, DynamicEngine.CreateRuntime (in the Microsoft.Scripting.Silverlight namespace) will create a ScriptRuntime all prepped for use in Silverlight; this significantly reduces the boilerplate hosting code:

In case you need to customize your ScriptRuntime, the DynamicEngine.CreateRuntimeSetup method is there to create a ScriptRuntimeSetup object configured for Silverlight, which then you can tweak things as necessary and create your own ScriptRuntime.

Note: The IronPython sources currently are broken for embedding, but in the next few days the sources should reflect what this post shows.

Testing that "import" works

Ok, great, the boilerplate hosting code doesn’t need to look hideous, but let’s get back on track.

Embedding IronPython in Silverlight - Importing test

Embedding IronPython in Silverlight – importing test (sources)

Here’s a quick test of IronPython’s ability to import various modules in Silverlight, testing this exact code works while being embedded:

None of these worked when I first wrote the tests, since there was an exception being thrown in the XAP-virtual-filesystem, reported yesterday on the IronPython mailing list. But with that fixed, the import bar.baz case still failed:

[FAIL]
Traceback (most recent call last):
  at test_import in foo.py, line 5
ImportError: No module named bar.baz

Here's the layout of the Python files in the XAP

foo.py
bar/
bar/__init__.py
bar/baz.py

Application.GetResourceStream("bar/__init__.py") was returning null, though bar/__init__.py was definitely inside the XAP. However, bar/__init__.py was empty, and it turns out that Application.GetResourceStream returns null if the file is empty as well as if it doesn’t exist! Putting a single space in bar/__init__.py (or anything that will make the file not empty … I suggest a comment) causes it to be found, and then bar/baz.py can be imported properly.

So, moral of the story:
“an empty file in the XAP is a non-existent file!”

Anyway, I hope that clears up some of the issues most people initially face with embedding IronPython in Silverlight. Let me know if there are any more issues.

Note: As I said before, the current IronPython sources are broken for embedding, but in the next few days the sources should reflect what this post shows. If you’re impatient, grab these binaries.