bytecodealliance / componentize-py

Apache License 2.0
130 stars 13 forks source link

Allow dynamic imports in sandbox example #91

Open kyleconroy opened 2 months ago

kyleconroy commented 2 months ago

I'd like to execute code using the sandbox example, but am running into an issue. I want to allow exec'd code to import packages, but if I don't import packages in the host script, the guest code won't run.

# Guest code
import json

print(json.dumps({"message": "Hello"}))
# Works
import sys
import json

from command import exports

class Run(exports.Run):
    def run(self):
        with open(sys.argv[1]) as f:
            code = f.read()
            exec(code)
# Fails
import sys

from command import exports

class Run(exports.Run):
    def run(self):
        with open(sys.argv[1]) as f:
            code = f.read()
            exec(code)
dicej commented 2 months ago

Thanks for reporting this, @kyleconroy. This sort of a duplicate of #23, but with a twist: wasmtime-py can't currently handle composed components (i.e. components that contain subcomponents), which is what wasi-virt generates, so the solution I proposed in that issue won't work until/unless wasmtime-py gains support for subcomponents.

An alternative approach would be to modify the sandbox example to allow access to a host-provided filesystem via wasi:filesystem, but then we hit another wasmtime-py limitation: no support for WASI (i.e. the wasmtime-wasi crate is only available for use in the Rust API for Wasmtime, not the Python one). It would certainly be possible to write a pure Python wasi:filesystem implementation that works with wasmtime-py, but it wouldn't be a quick task.

In short, we'd need to address this on both the componentize-py and wasmtime-py sides, and it will be a substantial amount of work. I don't expect I'll have time for it anytime soon, but I'd be happy to mentor anyone who wants to take a stab at it.

dicej commented 2 months ago

I just had a wild idea: we could optionally iterate over all known modules during pre-initialization and import them one by one (skipping any not currently supported like ssl). Not sure how much bloat that would add to the resulting component, but it would theoretically address this issue.

kyleconroy commented 2 months ago

You know, I was thinking the same thing as a workaround. Just add an import for every known module in the standard library. I can try that out and see how big the component becomes.

kyleconroy commented 2 months ago

With no imports, cli.wasm ended up being 33mb. After importing everything it was 43mb. Not too bad!

dicej commented 2 months ago

Yeah, that's not bad.

You probably already know this, but for anyone else reading: you can also import third-party packages (e.g. NumPy) the same way.

dicej commented 2 months ago

BTW, wasm-tools strip -a can reduce the component size quite a bit if desired.