Accessing Files Quick Reference#

For development of modules to use in Pyodide, the best experience comes from using Pyodide in Node and mounting the development directory into Pyodide using the NodeFS. In the NodeFS, all changes to your native file system are immediately reflected in Pyodide and vice versa.

If your code is browser-only, you can use the Chrome NativeFS for development. This will not automatically sync up with your native file system, but it is still quite convenient.

In Node.js#

It’s recommended to use pyodide.mountNodeFS() to mount the host file system so that it is accessible from inside of Pyodide. For example if you have a Python package in a folder called my_package, you can do:

pyodide.mountNodeFS("my_package", "/path/to/my_package");
pyodide.runPython(`
import my_package
# ... use it
`);

In the browser#

To access local files in Chrome, you can use the File System Access API to acquire a directory handle and then mount the directory into the Pyodide file system with pyodide.mountNativeFS(). To acquire the directory handle, you have to fill out a folder picker the first time. The handle can subsequently be stored in the IndexedDB. You will still be prompted for read and write access, but you don’t have to deal with the folder picker again.

The following code is a good starting point:

const { get, set } = await import(
  "https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js"
);

/**
 * Mount a folder from your native filesystem as the directory
 * `pyodideDirectory`. If `directoryKey` was used previously, then it will reuse
 * the same folder as last time. Otherwise, it will show a directory picker.
 */
async function mountDirectory(pyodideDirectory, directoryKey) {
  let directoryHandle = await get(directoryKey);
  const opts = {
    id: "mountdirid",
    mode: "readwrite",
  };
  if (!directoryHandle) {
    directoryHandle = await showDirectoryPicker(opts);
    await set(directoryKey, directoryHandle);
  }
  const permissionStatus = await directoryHandle.requestPermission(opts);
  if (permissionStatus !== "granted") {
    throw new Error("readwrite access to directory not granted");
  }
  const { syncfs } = await pyodide.mountNativeFS(
    pyodideDirectory,
    directoryHandle,
  );
  return syncfs;
}

See (Experimental) Using the native file system in the browser for more information.

Downloading external archives#

If you are using Pyodide in the browser, you should download external files and save them to the virtual file system. The recommended way to do this is to zip the files and unpack them into the file system with pyodide.unpackArchive():

let zipResponse = await fetch("myfiles.zip");
let zipBinary = await zipResponse.arrayBuffer();
pyodide.unpackArchive(zipBinary, "zip");

You can also download the files from Python using pyfetch(), which is a convenient wrapper of JavaScript fetch():

await pyodide.runPythonAsync(`
  from pyodide.http import pyfetch
  response = await pyfetch("https://some_url/myfiles.zip")
  await response.unpack_archive()
`)