pyodide/docs/usage/accessing-files.md

3.1 KiB

(accessing_files_quickref)=

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 {js:func}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 {js:func}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 {ref}nativefs-api 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 {js:func}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 {py:func}~pyodide.http.pyfetch, which is a convenient wrapper of JavaScript {js:func}fetch:

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