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
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
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.
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
bar/__init__.py was definitely inside the XAP. However,
bar/__init__.py was empty, and it turns out that
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.