Deploying pyjs#
Prerequisites:#
Before we start, let’s introduce a few concepts and tools that are used in the pyjs workflow.
Emscripten-forge#
Emscripten-forge is similar to conda-forge and provides packages compiled to webassembly using emscripten.
Empack#
https://github.com/emscripten-forge/empack is a tool to “pack” conda environments into a set of files that can be consumed by pyjs.
Installation Steps#
So we assume there is a directory called /path/to/deploy where we will
put all files which need to be served to the user.
Define a conda environment#
Pyjs has a conda-like workflow. This means the first step
is to create an environment with the pyjs package installed
and all packages required for the project.
name: my-pyjs-env
channels:
- https://repo.prefix.dev/emscripten-forge/6x
- conda-forge
dependencies:
- pyjs-dev
- numpy
The name of the environment can be chosen by the user.
The channels section specifies the conda channels to use.
The emscripten-forge channel (https://repo.prefix.dev/emscripten-forge/6x)
is mandatory, it provides pyjs and all other packages compiled to WebAssembly.
The conda-forge channel is used for noarch (pure Python) packages.
pyjs-dev contains the pyjs Python module (pyjs) and the pyjs runtime
(libpyjs-static, with lib_js/pyjs/pyjs_runtime_browser.{js,wasm}).
Create the environment#
Assuming the yaml file above is called environment.yml and is in the current directory, the environment can be created using micromamba:
micromamba create -f environment.yml --platform emscripten-wasm32 --prefix /path/to/env
Copy pyjs#
Copy the pyjs binary from the environment to the deploy directory. This should move pyjs_runtime_browser.js and pyjs_runtime_browser.wasm to the deployment directory.
cp /path/to/env/lib_js/pyjs/* /path/to/deploy
Pack the environment#
After the environment is defined, the next step is to pack the environment using empack.
empack pack env --env-prefix /path/to/env --outdir /path/to/deploy
This will create a tarball for each package in the environment and a empack_env_meta.json file that describes the environment.
The html/JavaScript code#
The last step is to create a html file that loads the pyjs runtime and the packed environment.
<!DOCTYPE html>
<html>
<head>
<title>Pyjs Example</title>
<script src="pyjs_runtime_browser.js"></script>
<script>
async function runPyjs() {
let locateFile = function(filename){
if(filename.endsWith('pyjs_runtime_browser.wasm')){
return `./pyjs_runtime_browser.wasm`; // location of the wasm
// file on the server relative
// to the pyjs_runtime_browser.js file
}
};
let pyjs = await createModule({locateFile});
await pyjs.bootstrap_from_empack_packed_environment(
"./empack_env_meta.json", // location of the environment
// meta file on the server
"." // location of the packed
// environment on the server
);
// now we can use pyjs
pyjs.eval("print('hello world')");
}
runPyjs();
</script>
</head>
<body>
<h1>Pyjs Example</h1>
</body>
</html>