将 Jupyter Notebook 与 ESE 集成
18331 为本文评分:
3.8
将 Jupyter Notebook 与 ESE 集成
Zachary Norman 2016年3月4日,星期五
我在 NV5(前身是 L3Harris/Harris)工作期间,有机会接触一些前沿技术。其中一个很酷的技术就是 IDL 8.5 中增加的 IDL-Python 桥接。通过 IDL-Python 桥接,你可以轻松扩展 IDL,利用开源代码来完成那些 IDL 可能没有现成算法的任务。IDL-Python 桥接的另一个重要用途是访问 Jupyter Notebook,这是一种基于 Web 的 IDL 编程解决方案。
这让我思考,是否可以将 Jupyter Notebook 服务器作为 ENVI Services Engine (ESE) 的一个 rest 端点(一个网络地址)。事实证明这是可行的,并且它是一个出色的基于 Web 的解决方案,允许在 ESE 实例上交互式地使用 IDL 和 ENVI API。这不是通过 ESE 服务器来运行任务,而是通过在 ESE 服务器上的 Jupyter Notebook 来运行 IDL,是充分利用 ENVI + IDL 构建 Web 解决方案的绝佳方式。
本篇博客将逐步介绍从设置 IDL-Python 桥接、修改 Jupyter 配置文件到为 Jupyter 服务器创建 rest 端点所需完成的所有步骤。不要被博客的长度吓到,实际上在 ESE 上设置和运行 Jupyter Notebook 相当容易。如果你已经设置好 IDL-Python 桥接,那么在为 Python 安装好 Jupyter 之后,可以直接跳到第二步。
1) 安装 Python 并设置 IDL-Python 桥接
首先,你需要安装 Anaconda(带 Python 2.7,不是 Python 3.4/3.5),通过一个通用的谷歌搜索就能找到下载位置。在安装过程中,请确保不要勾选将 Anaconda 注册为系统 Python 或将 Anaconda 添加到 PATH 环境变量的选项。
安装好 Anaconda 后,你需要添加一些环境变量并打开命令提示符。安装后,我在批处理文件中使用以下内容来设置环境变量。这里假设 Anaconda 安装位置是 "C:\python_installs\Anaconda"(只需将这些路径替换为你实际的安装位置,可能有所不同):
@echo off
REM 更改目录,以便 Jupyter Notebooks 在指定位置创建
cd %PROGRAMDATA%\ipython\notebooks
REM 设置用于建立桥接的路径
REM 设置后,我们可以从命令行调用 python 或 IDL
set PATH=C:\python_installs\Anaconda;^
C:\Program Files\Exelis\IDL85\bin\bin.x86_64;^
%PATH%
set PYTHONPATH=C:\Program Files\Exelis\IDL85\bin\bin.x86_64;^
C:\Program Files\Exelis\IDL85\lib\bridges;
set PYTHONHOME=C:\python_installs\Anaconda
创建好包含这些内容的批处理文件后,打开一个命令提示符窗口,然后将 .bat 文件拖放到命令提示符窗口中并按回车键。接着,输入 "conda install Jupyter" 并等待 Python 安装 Jupyter Notebook 内核。你可能需要按 'y' 来确认下载/更新某些 Python 包。
下一步是将 IDL 内核添加到 ipython 的 notebooks 中(ipython 随 Jupyter 一起安装)。将文件 C:\Program Files\Exelis\IDL85\lib\bridges\IDL\kernel.json 复制到目录 C:\ProgramData\ipython\kernels\IDL 中。如果这些目录不存在,请先创建它们。
2) 修改 Jupyter Notebook 服务器的配置
由于我们需要让 Jupyter Notebook 成为一个公共服务器,以便通过主机 IP 地址访问,因此引入一些安全措施非常重要,以防止网络上的任何人在未经许可的情况下访问服务器。最简单的方法是添加密码。也可以选择设置 SSL 加密,但这里不打算介绍。如果你想设置 SSL,请访问:
https://jupyter-notebook.readthedocs.io/en/4.x/public_server.html
在创建密码之前,我们必须为 Jupyter 设置一些配置文件。为此,在上述步骤的同一命令提示符中输入:
python -m Jupyter Notebook --generate-config
完成后,我们现在将生成一个密码并设置一个公共 Jupyter 服务器。在同一命令提示符中输入以下内容来生成密码:
python
from notebook.auth import passwd
passwd()
输入密码后,你应该会看到类似于 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed' 的输出。此时,你可以将哈希密码添加到你的 jupyter_notebook_config.py 文件中。该文件的默认位置在你的主目录的 .jupyter 文件夹中,即 C:\Uers\YourUsername\.jupyter。打开该文本文件后,在底部添加以下行。确保用上面得到的哈希密码输出替换引号内的文本,否则这对你将不起作用。
c.NotebookApp.password = u'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'
接下来,我们必须在 jupyter_notebook_config.py 文件中再添加几项,以使服务器成为公共服务器,这意味着你可以通过你机器的 IP 地址访问它(在密码行下方添加以下几行):
**# 将 ip 设置为 '*' 以绑定到公共服务器的所有接口(IP地址)
c.NotebookApp.ip = '*'
c.NotebookApp.password = u'sha1:bcd259ccf...<你的哈希密码在此处>'
c.NotebookApp.open_browser = False为服务器访问设置一个已知的固定端口是一个好主意
c.NotebookApp.port = 9999**
最后,我们需要在 Jupyter Notebook 安全性中创建一个例外,允许将 Jupyter 网页嵌入到 HTML 的 iframe 中。将 Notebook 嵌入 iframe 使我们可以在 ESE 中创建一个 rest 端点,你可以直接访问该端点来打开 Jupyter Notebook。对于上面的同一个配置文件 "jupyter_notebook_config.py",添加以下几行。你应该将 URL 中的 yourhostname 替换为你机器的主机名。如果你不知道主机名,可以在命令提示符中输入 "HOSTNAME"(不带引号)。在添加到 URL 中 "yourhostname" 的位置之前,将所有字母转换为小写。
c.NotebookApp.tornado_settings = {
'headers': {
'Content-Security-Policy': "frame-ancestors 'http://yourhostname:9191/Jupyter/' 'self' "
}
}
3) 为 Jupyter Notebook 创建 rest 端点和 HTML
在 ESE 6.0 中,创建指向不同网页的新 rest 端点(URL)非常容易。我为 Jupyter Notebook 决定的 URL 是 http://你的.IP.地址:9191/jupyter。你需要创建三个小的文本文件来正确设置这个网页。首先,我们必须修改 ESE 的一个配置文件,让 ESE 知道这个新的 URL。为此,打开文本文件 C:\ENVIServer60\config.json,并在 requestHandlers 部分添加 "./requestHandlers/JupyterRequestHandler"(带引号)。requestHandlers 的 json 内容应该类似于以下内容:
"requestHandlers": [
"./requestHandlers/InfoRequestHandler",
"./requestHandlers/HelpRequestHandler",
"./requestHandlers/ESEClassicRequestHandler",
"./requestHandlers/ClusterRequestHandler",
"./requestHandlers/AdminConsoleRequestHandler",
"./requestHandlers/JupyterRequestHandler"
]
接下来,我们必须创建一个目录来存放此 rest 端点的一些 javascript、html 和 json 信息。在 "C:\ENVIServer60\requestHandlers" 目录下创建 JupyterRequestHandler 目录,然后打开文本编辑器。请注意,接下来的三个文本文件应放在 C:\ENVIServer60\requestHandlers\JupyterRequestHandler 目录内。第一个文本文件名为 handler.js,应包含以下内容:
/**
* This module exposes a /jupyter endpoint that can be used to access a jupyter notebook hosted on the
* ESE server
* @module JupyterRequestHandler
*/
var config = require('../../utils/configLoader').config;
var express = require('express');
var log = require('Logger').logger;
/**
* @class
* @implements {RequestHandler}
*/
function JupyterRequestHandler() {
// Load help pages for all modules
// Inherits docs from RequestHandler interface
this.init = function(app) {
var root = __dirname + '/../..';
app.use('/jupyter', express.static(__dirname));
};
}
module.exports = JupyterRequestHandler;
第二个文本文件将命名为 package.json,包含以下内容:
{
"name": "JupyterRequestHandler",
"version": "1.0.0",
"description": "Custom request handler that provides access to the Jupyter IDL notebook",
"main": "handler.js",
"dependencies": {},
"devDependencies": {},
"scripts": {}
}
最后一个文件将命名为 index.html,应包含以下内容。确保将 "你的.IP.地址" 替换为你机器的 IP 地址:
<!DOCTYPE html>
至此,设置完成。你只需要重启 ESE 并启动 Jupyter Notebook 服务器。要启动 Jupyter,只需在已设置好 IDL-Python 桥接的命令提示符中输入以下内容:
python -m jupyter notebook
服务器启动后,你应该能够在 Internet Explorer 中输入 http://你的.IP.地址:9191/jupyter,Jupyter Notebook 的登录界面就会弹出。祝你使用愉快!