Так сложилось, что программный пакет Jupyter как бы не в курсе о существовании виртуальных окружений Python, ключевого инструмента изоляции среды в Python. Информация по этой теме в Сети крайне разрознена. В этой статье собраны все известные автору способы обхода / смягчения этой проблемы; надеюсь, кому-то она поможет не тратить столько дней на задачу, которая должна была быть простой.
Архитектура системы Jupyter сложна. Подробнее можно почитать в документации Jupyter, в документации jupyter_server
, в документации jupyter_client
, а здесь справка тезисно:
-
Ядро (kernel) — независимый процесс, непосредственно исполняющий код на конкретном языке программирования (используя конкретный экземпляр интерпретатора). Предоставляет сетевой интерфейс с использованием протокола ZeroMQ для передачи исполняемого кода и получения результатов.
Ядро
ipykernel
использует IPython, программный пакет, реализующий Python с расширенными возможностями интерактивной работы.Спецификация ядра (kernel spec) — лёгкие метаданные о ядре со ссылкой на нужный интерпретатор. Установка ядра (install kernel) означает установку спецификации ядра; "установленное ядро" не тратит значительные ресурсы хранилища.
-
Сервер (server) и приложения (web applications) — компоненты, обеспечивающие выполнение пользовательских задач в среде Jupyter.
Сервер — процесс, управляющий пользовательскими сессиями, запущенными ядрами, доступом к файловой системе, предоставляющий REST API к своим функциям.
-
Большинство приложений являются расширениями сервера — они ведут себя так же, как сервер, но с некоторым добавленным функционалом и пользовательским интерфейсом (как правило — веб-интерфейсом).
Jupyter Notebook, JupyterLab относятся именно к таким приложениям — они дают доступ к редактированию блокнотов и выполнению кода (через ядра).
Могут существовать также приложения, использующие только REST API сервера, но примеры не известны автору.
Чтобы пользователь могу выбрать ядро для использования (а значит, выбрать язык программирования и конкретный экземпляр интерпретатора), сервер Jupyter выполняет поиск доступных спецификаций ядер. В случае Python, выбор конкретного экземпляра интерпретатора важен в частности потому, что это означает и выбор конкретного виртуального окружения. И здесь начинаются проблемы.
"Ядра устанавливается" либо глобально в систему, либо глобально для отдельного пользователя, либо локально в виртуальное окружение. При этом они делят общее пространство имён. Ядра у пользователя имеют приоритет над ядрами глобально в системе, но приоритет ядер в виртуальных окружениях не определён.
Jupyter Core реализует довольно примитивный механизм поиска спецификаций ядер (документация 1, 2). По умолчанию ищутся только глобально установленные ядра (если само приложение Jupyter исполняется в виртуальном окружении, оно видит локально установленные ядра вместо глобально установленных в системе). Можно через переменную окружения
JUPYTER_PATH
указать места для поиска локально установленных ядер.Расширение Jupyter для Visual Studio Code самостоятельно реализует функции приложения. Однако оно имеет более продвинутый механизм поиска спецификаций ядер. Спецификации ядер, размещённые в виртуальном окружении (в директории данных Jupyter
share/jupyter
), также подбираются и могут быть использованы пользователем. Они должны иметь локально (в отношении виртуального окружения) уникальные имена, однако они делят пространство имён с глобально установленными ядрами, просто с более высоким приоритетом.Блокнот Jupyter сохраняет ID (name) нужного для его исполнения ядра в своих метаданных (
kernelspec.name
).
Таким образом, отдельный блокнот требует ядро с определённым именем, это имя ищется в системе глобально. Это мешает переносимости и контролю версий.
Jupyter
В этом разделе описаны варианты использования оригинальной системы Jupyter.
Использование локальных ядер (предпочтительный способ)
Ядро устанавливается локально в виртуальное окружение. Установленные в системе приложения Jupyter настраиваются так, чтобы находить это ядро.
Особенности:
+ Простой порядок работы в случае с единственным виртуальным окружением для каждого блокнота.
Инструкция по настройке проекта (однократной):
Добавьте пакет
ipykernel
в зависимости Python (requirements.txt
/pyproject.toml
...).Выберите локальный ID для ядра (например,
python3_venv
).Не забывайте записывать ID ядра в каждый блокнот в метаданные (
kernelspec.name
).
Инструкция по установке проекта (в виртуальное окружение, после установки зависимостей Python):
-
Установите ядро, связанное с виртуальным окружением, в директорию этого виртуального окружения. Укажите ID ядра, используемый блокнотами (см. инструкцию по настройке проекта), вместо
NAME
. Опционально укажите отображаемое имя ядра вместоDISPLAY_NAME
(если не укажете, будет использовано ID ядра). ID/имя ядра нужно, чтобы позже найти его через интерфейс установленного в системе приложения Jupyter.python -m ipykernel --sys-prefix --name NAME [--display-name DISPLAY_NAME]
Примечание: Какое-то ядро
python3
устанавливается в виртуальное окружение уже при установкеipykernel
. Оно ссылается на интерпретатор Python какpython
; видимо, из-за этого код Jupyter, работающий вне виртуального окружения, запускает установленный в системе интерпретатор Python вместо соответствующего виртуальному окружению. Поэтому это ядро, по-видимому, бесполезно. См. также примечание в инструкции по использованию в разделе Расширение Jupyter для Visual Studio Code. -
Опционально, заранее сохраните в переменную окружения
JUPYTER_PATH
путь к данным Jupyter в виртуальном окружении<path
> — см. п. 1 в инструкции по использованию.-
Windows (PowerShell):
[System.Environment]::SetEnvironmentVariable('JUPYTER_PATH', "<path>;$env:JUPYTER_PATH", 'User')
-
UNIX (sh):
echo 'export JUPYTER_PATH="<path>:$JUPYTER_PATH"' >> ~/.profile
-
Инструкция по использованию:
-
Если при выполнении инструкции по установке Вы не сохранили в переменную окружения
JUPYTER_PATH
путь к данным Jupyter в виртуальном окружении, этот путь нужно добавить в переменную окружения сейчас. Добавьте в переменную окруженияJUPYTER_PATH
абсолютный путь (далее обозначаемый<path>
)$VIRTUAL_ENV/share/jupyter
, где следует заменить$VIRTUAL_ENV
на путь к директории, где развёрнуто виртуальное окружение. Для инструментовvenv
,virtualenv
можно просто в активном виртуальном окружении использовать подстановку переменной окруженияVIRTUAL_ENV
(активное виртуальное окружение не повлияет на дальнейшие шаги).-
Windows (PowerShell):
$env:JUPYTER_PATH = "<path>;$env:JUPYTER_PATH"
-
UNIX (sh):
export JUPYTER_PATH="<path>:$JUPYTER_PATH"
-
-
Запустите установленное в системе приложение Jupyter, например, Jupyter Notebook. (Если Вы всё ещё в виртуальном окружении, всё равно запустится именно приложение, установленное в систему, т.к. Вы не устанавливали приложения Jupyter в виртуальное окружение).
jupyter notebook
Используйте приложение Jupyter. Не забывайте выбирать нужное ядро (которое Вы установили локально) при работе с кодом Python.
Веб-приложение/сервер Jupyter внутри виртуального окружения
Нужные приложения Jupyter (или только сервер, если используется приложение, подключаемое по REST API) устанавливаются в виртуальное окружение.
Особенности:
+ Простой порядок работы в случае с единственным виртуальным окружением для проекта.
− Высокий расход ресурсов хранилища; пакет notebook
версии 7.4 со всеми зависимостями занимает порядка 264 МБ 12 тысячами файлов.
− Потенциальные проблемы с более сложными рабочими процессами из-за изоляции среды Jupyter от других проектов.
Инструкция по настройке проекта (однократной):
Опционально, добавьте нужные приложения Jupyter (например, пакет
notebook
) в список зависимостей Python (requirements.txt
/pyproject.toml
...).
Инструкция по установке проекта (в виртуальное окружение, после установки зависимостей Python):
-
Если Вы не добавили приложения Jupyter в зависимости Python.
Установите нужные приложения Jupyter (или только сервер Jupyter, если используется приложение, подключаемое по REST API) в виртуальное окружение.
Например, для веб-приложения Jupyter Notebook (пакет
notebook
):pip install -U notebook
Инструкция по использованию:
-
В виртуальном окружении запустить нужное приложение Jupyter:
Например, для веб-приложения Jupyter Notebook (пакет
notebook
):jupyter notebook
Использовать приложение Jupyter — ядро, выбранное по умолчанию, и будет актуально в виртуальном окружении.
Установка в систему ядер с определёнными именами (не рекомендуется)
См. другой способ в подразделе Использование локальных ядер.
Ядро устанавливается в систему (для пользователя или глобально). Установленные в системе приложения Jupyter видят это ядро без дополнительной настройки.
Особенности:
+ Относительно простой порядок работы в случае с единственным виртуальным окружением для каждого блокнота.
− Необходимо обеспечить уникальность ID ядра для проекта. При добавлении условно уникальной строки в ID оно может стать нечитаемым.
− Если необходимо иметь несколько ядер для одного блокнота (например, для нескольких виртуальных окружений), необходимо применять локальные правки к блокноту, что существенно усложняет контроль версий.
− Установленные спецификации ядер остаются в системе глобально и захламляют систему.
Инструкция по настройке проекта (однократной):
Добавьте пакет
ipykernel
в зависимости Python (requirements.txt
/pyproject.toml
...).Выберите ID для ядра, глобально уникальный в возможных условиях развёртывания (например,
<project-name>-<unique-id>
, где<unique-id>
— достаточно длинная уникальная строка).Не забывайте записывать ID ядра в каждый блокнот в метаданные (
kernelspec.name
).
Инструкция по установке проекта (в виртуальное окружение, после установки зависимостей Python):
-
Установите ядро, связанное с виртуальным окружением, в систему. Укажите ID ядра, используемый блокнотами (см. инструкцию по настройке проекта), вместо
NAME
. Опционально укажите отображаемое имя ядра вместоDISPLAY_NAME
(если не укажете, будет использовано ID ядра). ID/имя ядра нужно, чтобы позже найти его через интерфейс установленного в системе приложения Jupyter.python -m ipykernel --user --name NAME [--display-name DISPLAY_NAME]
Эта команда устанавливает ядро для текущего пользователя. Опционально Вы можете установить ядро глобально, убрав опцию
--user
.
Инструкция по удалению проекта (помимо других действий):
-
Удалите ядро, связанное с виртуальным окружением, из системы. Укажите ID ядра, используемый блокнотами (см. инструкцию по настройке проекта), вместо
NAME
.jupyter kernelspec uninstall NAME
Инструкция по использованию:
-
Запустите установленное в системе приложение Jupyter, например, Jupyter Notebook. (Если Вы всё ещё в виртуальном окружении, всё равно запустится именно приложение, установленное в систему, т.к. Вы не устанавливали приложения Jupyter в виртуальное окружение).
jupyter notebook
Используйте приложение Jupyter. Не забывайте выбирать нужное ядро (которое Вы установили в систему, по его уникальному ID/имени) при работе с кодом Python.
Расширение Jupyter для Visual Studio Code
В этом разделе описано использование расширения Jupyter для Visual Studio Code.
Ядро устанавливается локально в виртуальное окружение. Установленные в системе приложения Jupyter настраиваются так, чтобы находить это ядро.
Особенности:
+ Простой порядок работы в случае с единственным ядром для каждого блокнота.
− Несовместимость блокнотов, созданных в расчёте на использование этого подхода, со многими другими способами изоляции в Jupyter (кроме установки приложений Jupyter в локальные окружения).
− Ограниченный функционал и нестабильность расширения Jupyter для Visual Studio Code.
Инструкция по настройке проекта (однократной):
Добавьте пакет
ipykernel
в зависимости Python (requirements.txt
/pyproject.toml
...).
Инструкция по использованию:
Запустите Visual Studio Code.
Откройте директорию проекта в VS Code.
-
Если VS Code запрашивает выбор автоматически обнаруженного виртуального окружения, согласитесь.
Иначе укажите своё виртуальное окружение самостоятельно.
Используйте VS Code с расширением Jupyter. Не забывайте при открытии любого блокнота проверять, что выбрано корректное ядро Jupyter (принадлежащее корректному виртуальному окружению). (Кнопка для выбора ядра для открытого блокнота находится в верхнем правом углу области содержимого вкладки; по умолчанию Вы увидите название выбранного виртуального окружения; если ядро не выбрано, на кнопке написано Select Kernel.)
Примечание: Каким-то неизвестным автору образом расширение Jupyter для Visual Studio Code обходит проблему, описанную в примечании к инструкции по установке в подразделе Использование локальных ядер, не изменяя спецификацию ядра.