这篇文章记录一下基于 jupyterlab做自定义接口和插件的二次开发过程和关键点
目前我们给甲方提供的机器学习平台是基于k8s + jupyterlab实现的, 这样的好处是数据科学家可以在一个相对隔离的环境里开发自己的数据应用, 但是缺点是每个人之间无法共享自己开发的脚本给其他人. jupyter生态并不提供这样的功能, hub这种多用户系统也没有. 所以我们的思路是用第三方云存储来实现文件的共享. A用户将自己的开发的脚本上传到云存储并决定共享给B, 然后B用户接到A用户共享文件给他的通知, 从云存储上下载该文件. 因为我不做前端开发, 所以, 我只记录我这边python端实现的思路和方法.
A 决定共享一个文件给B
A 上传文件到S3
python端记录A的username和文件名和共享给B的用户名信息并存入数据库
B的lab中通过自定义接口获取数据库中共享给自己的信息
B通过S3下载该文件到自己的文件夹里面
这里面比较复杂的地方在于hack jupyterlab的源码, 增加自定义的接口. 当然, 我没有耐心去看jupyterlab的插件开发文档, 直接读源码, 分析他的API入口, 然后自己写方法实现是我等糙人的一贯行事风格.也许这样不够规范, 但是足够简单粗暴直接.
首先在 jupyterlab/handlers/创建一个custom_handler.py的文件.# 引入notebook的APIHandler, 作用是继承环境变量, 以及jupyter的各种配置项
from notebook.base.handlers import APIHandler
class ShareNotebookHandler(APIHandler):
# APIHandler继承自Tornado的web.RequestHandler, 所以, 继承的类不能用__init__做入口, 需要用initialize方法做入口, 这是tornado规定的.
def initialize(self, uploader):
self.uploader = uploader
# 这里获取用户的 notebook 所在的文件夹, 并替换为绝对路径, 这是个 Lazy 的 Config
# 由于环境是k8s, notebook_dir 是有 lab 启动参数设定的, 是个 LazyConfig, 所以可以获取到, 如果是普通环境, 需要用 server_dir 代替
# Jupyter 的 LazyConfig 的本质是一个 traitlets 对象, 所以需要str转换一下变量类型.
self.working_dir = str(self.application.settings['config']['LabApp']['notebook_dir'].
replace('~', os.path.expanduser('~')))
custom_config_dir = str(self.application.settings['config_dir'])
# CustomConfig 和 ShareNotebookMet