How I implemented relative imports with Pyodide

evanhahn.com2025年12月11日 00:00

I was recently playing with Pyodide, the WebAssembly Python runtime. I wanted to have my main code import a utility file. Something like this:

# in main code
import util
print(util.triple(5))

# in util.py
def triple(n):
    return n * 3

This took me awhile to figure out! I’m not convinced I have the best solution, but here’s what I did:

  1. Fetch util.py with fetch.
  2. Save it to Pyodide’s virtual file system.
  3. Run the main code!

Here’s what my JavaScript loader code looked like:

// Fetch `util.py` source
const response = await fetch("util.py");
if (!response.ok) throw new Error("Failed to load util.py");
const utilSource = await response.text();

// Save it to Pyodide's virtual file system.
// Pyodide can import modules in `/home/pyodide`.
pyodide.FS.writeFile("/home/pyodide/util.py", utilSource);

// Run the main code!
pyodide.runPython(`
import util
print(util.triple(5))
`);

This worked for me, but I wish there were a cleaner solution. Maybe Pyodide has a way to hook into import? If you have a better solution, please reach out!