{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Installing and importing Python packages in the Pyodide kernel\n", "\n", "The default Python kernel for JupyterLite powered by [pyodide](https://pyodide.org),\n", "supports installing packages from a number of sources:\n", "\n", "- packages distributed with `pyodide`\n", " - these do not need to be explicitly installed\n", "- packages and shims distributed along with the kernel\n", " - this includes some compatibility shims for the Jupyter stack\n", "- custom packages deployed with a JupyterLite site\n", "- pure python wheel packages on PyPI\n", " - ending in _exactly_ `py3-none-any.whl`\n", "- or specially compiled wheels for the _exactly_ the version of pyodide and emscripten\n", " installed\n", " - ending in e.g. `cp310-cp310-emscripten_3_1_14_wasm32.whl`" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Recommended: `%pip install -q`\n", "\n", "The **recommended** way to install packages is the `%pip` magic:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install -q \"traitlets >=5\" ipython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{hint}\n", "- `%pip` helps keep your notebooks **portable** between different IPython runtimes.\n", "- `-q` helps keep this \"setup\" step reasonable when run under `ipykernel`\n", "```\n", "\n", "`%pip` supports a number of additional options:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip --help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `--requirements`\n", "\n", "In addition to (or instead of) package names, any number of `--requirements` (or\n", "shorthand `-r`) may be given, pointing to [requirements files][reqs-txt].\n", "\n", "[reqs-txt]: https://pip.pypa.io/en/stable/reference/requirements-file-format\n", "\n", "These can be relative or absolute (though this can be tricky to predict)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install -r data/requirements.txt -r ../data/more-requirements.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{hint}\n", "Using a `requirements.txt` is a good way to separate your content from your environment,\n", "and could be combined with other techniques to make even more portable notebooks.\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### `requirement.txt` lines\n", "\n", "A number of simple types of requirement specifications are\n", "[supported](./data/requirements.txt), including:\n", "\n", "- package names\n", "- package names with version specifiers supported by `micropip`\n", "- URLs of `.whl` archives\n", "- `-r` to _more_ requirements files\n", " - relative to the _requiring_ file, not the `%pip` working directory" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some known **unsupported** features:\n", "\n", "- `.` or other local in-development paths\n", " - but you _could_\n", " - `%pip install` a build tool (e.g. `flit`)\n", " - use its Python API\n", " - install the resulting `.whl`\n", "- `--editable` (or `-e.`) local or remote paths\n", "- any version control system (VCS) paths\n", "- non-`.whl` URLs or local archives\n", "- `--constraint` (or `-c`) constraint files" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Dealing with (missing) dependencies\n", "\n", "Even if a PyPI package _would be_ installable in the Pyodide kernel, sometimes its\n", "dependencies won't be." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " %pip install jupyter_server\n", "except Exception as err:\n", " print(err)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### `--verbose`\n", "\n", "As the real `pip` doesn't have an equivalent, `%pip` in the Pyodide kernel maps the\n", "`--verbose` flag to `keep_going`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " %pip install --verbose jupyter_server\n", "except Exception as err:\n", " print(err)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{warning}\n", "Leaving this on for real `pip` generates a **lot** of output!\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `--no-deps`\n", "\n", "If some missing dependencies don't bother you, you can forge ahead without _any_\n", "dependencies with the `--no-deps` flag." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install jupyter_server --no-deps\n", "import jupyter_server\n", "\n", "jupyter_server.__version__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While importable, it won't have all of its features, and may require special approaches\n", "to access features." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " import jupyter_server.services.contents.filemanager\n", "except Exception as err:\n", " print(err)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Going down this road can be long, depending on how much you really need a particular\n", "function." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Hard Way\n", "\n", "The `piplite` package is importable, and can be used directly." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Importing `piplite`\n", "\n", "`piplite` needs to be imported before it is used." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import piplite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This package **won't** be installable in a \"traditional\" IPython installation, so you\n", "can gate it with an import check:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " import piplite\n", "except ImportError:\n", " piplite = None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `piplite.install`\n", "\n", "> `piplite.install` is a wrapper around\n", "> [`micropip.install`](https://pyodide.org/en/stable/usage/loading-packages.html#micropip),\n", "> and offers more browser-focused options than `%pip`\n", "\n", "```{warning}\n", "Due to browser limitations, `piplite.install` is an _asynchronous` function, so it must be `await`ed.\n", "```\n", "\n", "`piplite.install` supports either a single package:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "await piplite.install(\"traitlets\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "or a list of packages:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "await piplite.install([\"traitlets\", \"IPython\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It also has many additional options:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "?piplite.install" ] } ], "metadata": { "kernelspec": { "display_name": "Python (Pyodide)", "language": "python", "name": "python" }, "language_info": { "codemirror_mode": { "name": "python", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8" } }, "nbformat": 4, "nbformat_minor": 4 }