- 数据分析
- 数据可视化
- 大数据
- 后端
- 前端
- 任务调度
【免费下载链接】zeppelin
Web-based notebook that enables>项目地址:https://gitcode.com/gh_mirrors/zeppe/zeppelin
Apache Zeppelin 的 Python 解释器模块(python/)是整个项目中数据分析和机器学习场景最常用的解释器之一。本文以仓库中的 python/README.md 为核心骨架,结合python模块的源码实现、测试用例与资源文件,系统讲解两类 Python 解释器(原生 Python 解释器与 IPython 解释器)的进程模型、Py4J 双向通信机制、matplotlib 内联绘图、Pandas DataFrame SQL 查询,以及 Conda/Docker 环境管理与单元测试方法。读完本文,你将能理解 Zeppelin 与 Python 进程之间“如何启动、如何通信、如何中断、如何渲染结果”的完整链路,并掌握该模块的开发前置条件与测试命令。
模块总览:一个模块,多类解释器
Apache Zeppelin 的 Python 支持由独立的 Maven 模块python(artifactId 为zeppelin-python)承载,其核心定位在 python/pom.xml 中描述为“Zeppelin: Python interpreter”,解释器名称注册为python。该模块基于zeppelin-interpreter-parent构建,并依赖zeppelin-jupyter-interpreter-shaded、commons-exec、py4j等组件,其中 py4j 版本由python.py4j.version属性声明。
README 对该模块给出了高度凝练的定位:
Python interpreter for Apache Zeppelin——一个面向 Apache Zeppelin 的 Python 解释器。
从 python/src/main/java/org/apache/zeppelin/python 目录的源码结构看,该模块实际包含了五类可用的解释器:
| 解释器前缀 | 实现类 | 说明 |
|---|---|---|
%python | PythonInterpreter | 原生(vanilla)Python 解释器,只要求机器上装有 Python;若 IPython 前置条件满足,会优先委派给 IPython 解释器 |
%python.ipython | IPythonInterpreter | 基于 Jupyter 内核的 IPython 运行时,体验接近 Jupyter Notebook |
%python.sql | PythonInterpreterPandasSql | 通过pandasql对%python中定义的 Pandas DataFrame 执行 SQL 查询 |
%python.conda | PythonCondaInterpreter | 管理 Conda 环境,可在不同 Python 环境间切换 |
%python.docker | PythonDockerInterpreter | 在指定的 Docker 容器内运行 Python 进程 |
其中前两类是 README 正文明确讲解的主体(“Python interpreter”与“IPython interpreter”),其余几类作为同一模块内的补充能力,本文也会结合源码做对应说明。
架构核心:ProcessBuilder 启动 Python 子进程
README 的 Architecture 一节给出了整个模块最根本的设计:
Current interpreter implementation spawns new system python process through
ProcessBuilderand re-directs it's stdin\strout to Zeppelin
即:Zeppelin(JVM 侧)通过ProcessBuilder启动一个独立的系统 Python 进程,并把该进程的 stdin/stdout 重定向到 Zeppelin,实现“Zeppelin 进程 ↔ Python 进程”两个进程间的协作。这一设计让 Python 代码运行在独立进程中,与 JVM 完全隔离,避免 Java 崩溃波及 Python 会话,同时也让 Python 侧的库(pandas、numpy 等)天然可用。
在 PythonInterpreter.java 中,这一启动逻辑落在createGatewayServerAndStartScript()方法(第 126–168 行)中,完整链路如下:
- 启动 Py4J GatewayServer:在 JVM 侧通过
RemoteInterpreterUtils.findRandomAvailablePortOnAllLocalInterfaces()随机选择一个可用端口,使用PythonUtils.getLocalIP(properties)获取本机 IP 作为服务地址,并通过PythonUtils.createSecret(256)生成 256 位随机密钥用于鉴权,随后gatewayServer.start()开启服务; - 生成 Python 工作目录:
createPythonScript()在临时目录(macOS 上强制使用/tmp,避免 Docker 挂载/var被拒)中创建pythonWorkDir,并把zeppelin_python.py、zeppelin_context.py、backend_zinline.py、mpl_config.py以及内置的 py4j 源码包拷贝进去; - 拼装启动命令:
getPythonExec()(第 236–245 行)按优先级{conda.env.name}/bin/python > condaPythonExec > zeppelin.python 属性决定 Python 可执行文件路径,默认值为python;命令末尾追加pythonWorkDir/zeppelin_python.py <serverAddress> <port>作为入口脚本参数; - 启动并等待就绪:通过自定义的
PythonProcessLauncher(继承自ProcessLauncher)启动进程,并调用waitForReady(MAX_TIMEOUT_SEC * 1000)等待 Python 侧回报初始化完成,MAX_TIMEOUT_SEC为 30 秒;超时或启动失败会抛出 IOException 并附带错误信息。
setupPythonEnv()(第 214–223 行)还会把pythonWorkDir和内置 py4j 源码 zip 追加进PYTHONPATH环境变量,同时将PY4J_GATEWAY_SECRET注入环境,供 Python 侧连接 GatewayServer 时使用。
README 描述的“flush reader”协议与当前实现的演变
README 的 Technical overview 一节详细描述了早期的指令-响应协议:
Interpreter sends command to python with a Java
outputStreamWiterand read from anInputStreamReader. To know when stop reading stdout, interpreter sendsprint "*!?flush reader!?*"after each command and reads stdout until he receives back the*!?flush reader!?*.
即通过 stdin 写指令、从 stdout 读结果,并以特殊标记串*!?flush reader!?*作为一次执行结束的边界。这一机制在当前源码中已被基于 Py4J 的同步调用协议取代(README 作为模块文档保留了最初的设计描述)。从 zeppelin_python.py 的主循环(第 127–214 行)可以看到当前实现:
- Python 进程启动后先调用
intp.onPythonScriptInitialized(os.getpid())向 JVM 回报 PID; - 然后用自定义的
Logger类接管sys.stdout与sys.stderr,把 Python 的打印输出转发到 JVM 侧(intp.appendOutput(message)),最终写入当前段落的InterpreterOutput; - 主循环中通过
intp.getStatements()阻塞等待 JVM 下发语句,执行结束后调用intp.setStatementsFinished(out, error)回报结果。
对应地,PythonInterpreter.java 中的callPython()(第 360–376 行)负责把PythonInterpretRequest置入共享字段并通过statementSetNotifier唤醒 Python 进程,随后在statementFinishedNotifier上等待执行完成;getStatements()与setStatementsFinished()分别是 Python 侧反向调用的入口。两个线程之间用一对synchronized监视器完成握手,这也是close()中重置这两个监视器状态的原因(否则重启解释器时会因状态残留导致后续执行失败)。
Python 侧执行的编译模式
zeppelin_python.py 对用户语句的处理非常精细:先将整段语句编译为 AST(ast.PyCF_ONLY_AST),再按exec/single两种模式分段执行——除最后一条语句外的语句以exec模式编译执行,最后一条语句以ast.Interactive+single模式执行,从而保证“最后一行表达式的求值结果能被打印到 stdout”,行为与交互式解释器一致。语句执行失败时,脚本会从 traceback 中正则提取出错行号,回报形如Fail to execute line N: <语句内容>的错误信息。
开发前置条件与 Python 2/3 兼容约定
README 的 Dev prerequisites 一节列出了模块开发者在本地运行与贡献代码时需要注意的事项,这些约定直接体现在资源文件的编写风格中:
- 需要安装 Python 2 或 Python 3,并确保每个版本都装有py4j(0.9.2)与matplotlib(1.31 或更新)。需要说明的是,当前仓库 PythonConstants.java 中内置 py4j 的版本常量已是
0.10.9.7(PY4J_VERSION = "0.10.9.7"),README 中的 0.9.2 属于文档撰写时的旧版本要求,实际以当前仓库为准; - 单元测试只校验解释器逻辑,不会启动任何真实 Python 进程:测试中用“一个简单把输入原样输出的类”来 mock Python 进程,因此开发者无需在本地配置完整 Python 环境也能跑通核心逻辑测试;
- 写在引导脚本(README 时代名为
bootstrap.py与bootstrap_input.py)中的代码必须同时兼容 Python 2 和 Python 3。当前仓库中这两个文件已演化为 zeppelin_python.py、zeppelin_context.py 等资源,其中仍然贯彻了双版本兼容写法——例如 zeppelin_python.py 第 88–94 行针对 Python 3.8 之后ast.ModuleAPI 的变化做了版本分支兼容; - Python 代码遵循PEP8编码规范。
运行完整测试套件
README 明确给出了运行 Python 模块全部单元测试(包括依赖真实 Python 解释器与 pandas、pandasql 等外部库的测试)的命令:
./mvnw -Dpython.test.exclude='' test -pl python -am其中-Dpython.test.exclude=''表示清空默认的测试排除项,-pl python -am表示只构建python模块及其依赖模块。测试代码集中在 python/src/test/java/org/apache/zeppelin/python 目录下,例如:
- BasePythonInterpreterTest.java:解释器基础逻辑的测试基类;
- PythonInterpreterTest.java:原生 Python 解释器测试;
- PythonInterpreterMatplotlibTest.java:matplotlib 内联绘图测试;
- IPythonInterpreterTest.java、PythonCondaInterpreterTest.java、PythonDockerInterpreterTest.java:对应各子解释器的测试;
- PythonInterpreterPandasSqlTest.java:Pandas SQL 能力测试。
Py4J 支持:让 Python 代码调用 Java 对象
README 的 Py4j support 一节强调:
[Py4j] enables Python programs to dynamically access Java objects in a JVM. It is required in order to use Zeppelin dynamic forms feature.
Py4J 是这条跨语言桥的核心:它让运行在独立进程中的 Python 代码能够反向访问 JVM 内的 Java 对象,从而把 Zeppelin 的**动态表单(Dynamic Forms)**能力直接带进 Python 段落。没有 Py4J,Python 解释器就无法实现z.input()、z.select()这类需要与 JVM 侧 ZeppelinContext 交互的功能。
整个桥接在启动阶段完成,README 的技术描述为:
[Py4J] Python and Java libraries are used to load input zeppelin Java class into the python process (make java code with python code !). Therefore the interpreter can directly create Zeppelin input form inside the Python process... JVM opens a random open port to be accessible from python process.
对照源码可以还原这条链路:
- JVM 侧在随机端口上启动
GatewayServer,入口对象(entry point)就是PythonInterpreter实例本身(PythonUtils.java 的createGatewayServer()使用GatewayServerBuilder并同时设置authToken、javaAddress与callbackClient); - 端口、IP、密钥通过命令行参数与环境变量
PY4J_GATEWAY_SECRET传给 Python 进程; - zeppelin_python.py 第 96–107 行读取
sys.argv[1](host)与sys.argv[2](port),用JavaGateway连接 JVM,并通过gateway.entry_point拿到 Java 侧的PythonInterpreter对象; - 随后导入 zeppelin_context.py 中的
PyZeppelinContext,执行z = __zeppelin__ = PyZeppelinContext(intp.getZeppelinContext(), gateway),把 Java 侧的PythonZeppelinContext(PythonZeppelinContext.java)包装为 Python 侧的全局对象z; - 引导脚本检测到 py4j 库可用时,才把
z、__zeppelin__等注入用户命名空间——这与 README 中“bootstrap_input.py 仅在检测到 Python 进程内有 py4j 时才发送”的描述一脉相承。
得益于这条桥,Python 段落内可以像下面这样直接使用动态表单(完整示例也见 docs/interpreter/python.md 的 Dynamic Forms 章节):
%python ### 输入框表单 print(z.input("f1", "defaultValue")) ### 下拉选择表单 print(z.select("f2", [("o1", "1"), ("o2", "2")], "o1")) ### 复选框表单 print("".join(z.checkbox("f3", [("o1", "1"), ("o2", "2")], ["o1"])))ZeppelinContext 的常用 API
Python 解释器创建全局变量z代表 ZeppelinContext,README 虽未逐条罗列,但动态表单只是其中一部分能力。结合 docs/interpreter/python.md 的 API 表,z对象还提供:
z.put(key, value)/z.get(key)/z.remove(key):读写/删除 Zeppelin 分布式资源池中的对象,实现跨解释器共享;z.getAsDataFrame(key):把资源池中表类型对象(如 JDBC 结果)转换为 pandas DataFrame;z.angular(name)/z.angularBind(name, value)/z.angularUnbind(name):操作 Angular 对象;z.show(p):在 Zeppelin 中以表格或字符串形式展示 Python 对象,pandas DataFrame 会走内置 Table 显示系统;z.textbox / z.select / z.checkbox以及对应的z.noteTextbox / z.noteSelect / z.noteCheckbox:段落级与笔记级动态表单;z.run(paragraphId)/z.runNote(noteId):触发段落或整篇笔记执行;z.configure_mpl(...):配置 matplotlib 内联绘图的尺寸与格式(见下节)。
Matplotlib 内联显示机制
README 指出:
Matplotlib figures are displayed inline with the notebook automatically using a built-in backend for zeppelin in conjunction with a post-execute hook.
即 Zeppelin 为 Python 提供了一个内置的 matplotlib 后端,配合一个post-execute hook,实现图表自动内联显示。具体实现分布在两个层面:
- Java 侧:
PythonInterpreter.open()(PythonInterpreter.java 第 79–123 行)在注册解释器 Hook 时写入registerHook(HookType.POST_EXEC_DEV.getName(), "__zeppelin__._displayhook()"),把_displayhook()注册为执行后的收尾动作;zeppelin_python.py 主循环中也会取出全局与用户级post_exechook 并在语句之后执行; - Python 侧:backend_zinline.py 实现了一个静态(非交互式)的 matplotlib 后端,它基于
backend_agg,通过自定义的Show类在调用show()时把当前所有 figure 渲染为图像字节流,并由 mpl_config.py 提供尺寸、格式等配置项(默认 600x400、PNG)。
默认情况下,下面这段代码就会把折线图内联展示在段落输出中(示例取自 docs/interpreter/python.md):
%python import matplotlib.pyplot as plt plt.plot([1, 2, 3])如果需要调整尺寸与格式,可以用内置的z.configure_mpl():
z.configure_mpl(width=400, height=300, fmt='svg') plt.plot([1, 2, 3])上面会输出 400x300 的 SVG 图(默认是 600x400 的 PNG)。若内联后端加载失败,还可以回退用z.show(plt)手动渲染:
%python import matplotlib.pyplot as plt plt.figure() # ... 绘图代码 z.show(plt, width='50px') z.show(plt, height='150px', fmt='svg') plt.close()z.show()的可选参数同样支持width、height与fmt(png 或 svg)。README 提到在pyspark解释器中还能以%angular输出实现“一个段落绘图、另一个段落更新”,这属于同类机制的延伸能力。
代码补全:__zeppelin_completion__
除了执行语句,原生解释器还通过 zeppelin_python.py 中定义的PythonCompletion类提供代码补全:Java 侧在收到补全请求时构造__zeppelin_completion__.getCompletion('<目标字符串>')语句下发(见 PythonInterpreter.java 的completion()方法),Python 侧按“是否含点号”区分对象名补全与方法名补全,用dir()枚举命名空间或对象属性,过滤掉__开头的内建项后以 JSON 数组回报。补全请求走独立的isForCompletion标记,不触发 post-exec hook,也不会把补全结果当作普通输出打印。
中断执行:为何用kill -SIGINT而不是 Java 信号
README 明确指出原生ProcessBuilder的局限:
JavaBuilder can't send SIGINT signal to interrupt paragraph execution. Therefore interpreter will directly send a
kill SIGINT PIDto python process to interrupt execution. Python process catches SIGINT signal with some code defined in bootstrap.py
由于 Java 的ProcessBuilder无法向子进程发送 SIGINT,PythonInterpreter.java 的interrupt()方法(第 412–420 行)改而记录 Python 进程的 PID(由onPythonScriptInitialized(os.getpid())回报),然后通过系统命令直接发送信号:
Runtime.getRuntime().exec("kill -SIGINT " + pythonPid);而在 Python 侧,zeppelin_python.py 开篇(第 29–30 行)有一段关键处理:当 Zeppelin 由zeppelin-daemon.sh(nohup)启动时,Python 进程会继承SIGINT=SIG_IGN,CPython 会保持忽略而不安装KeyboardInterrupt处理器,导致取消操作失效;因此脚本在启动时显式检查并恢复默认的 SIGINT 处理器:
if signal.getsignal(signal.SIGINT) == signal.SIG_IGN: signal.signal(signal.SIGINT, signal.default_int_handler)对于非 UNIX/Linux 系统(无法kill),interrupt()会退化为直接close()解释器。这解释了段落取消(cancel)在 Python 解释器上完整生效的底层原理。
%python.sql:对 Pandas DataFrame 执行 SQL
README 提到:
%python.sqlsupport for Pandas DataFrames is optional but can be downloaded from here if user does not have one installed.
其中所指的“downloadable library”就是pandasql。PythonInterpreterPandasSql.java 的设计目标是“复刻%spark.sql之于 Spark DataFrame 的体验”:它的open()通过pythonInterpreter.bootstrapInterpreter("python/bootstrap_sql.py")在原生解释器中注入 SQL 依赖,interpret()则将用户 SQL 包装为 Python 调用并委派给原生解释器执行:
return pythonInterpreter.interpret("z.show(pysqldf('" + st.trim() + "'))", context);也就是说,每条%python.sql语句最终都会以z.show(pysqldf('<SQL>'))的形式运行,查询结果经z.show()走 Zeppelin 内置 Table 显示系统完成可视化。前提是 Python 环境中安装了:
pip install pandas pip install -U pandasql典型的跨段落用法(示例见 docs/interpreter/python.md):
- 第一段(
%python)定义 DataFrame:
import pandas as pd rates = pd.read_csv("bank.csv", sep=";")- 第二段(
%python.sql)直接查询:
SELECT * FROM rates WHERE age < 40因为%python.sql与%python属于同一解释器组、共享同一 Python 进程命名空间,所以第一段定义的rates可以直接被 SQL 引用。默认最多展示 1000 行,可通过zeppelin.python.maxResult调整。
环境管理:Conda 与 Docker 子解释器
Python 运行环境的多样化是实际使用中的刚需。除 README 正文外,模块源码还提供了两个环境管理解释器,它们与原生解释器共享同一调度器,确保%python.conda/%python.docker段落与%python段落顺序执行(见 PythonCondaInterpreter.java 与 PythonDockerInterpreter.java 的getScheduler())。
%python.conda:Conda 环境切换
PythonCondaInterpreter.java 通过正则解析子命令并调用系统conda命令,支持(用法详见 docs/interpreter/python.md):
%python.conda info # 查看 Conda 信息 %python.conda env list # 列出 Conda 环境 %python.conda create --name [ENV NAME] # 创建环境 %python.conda activate [ENV NAME] # 激活环境(会重启 Python 进程) %python.conda deactivate # 取消激活 %python.conda list # 查看当前环境的已安装包 %python.conda install [PACKAGE NAME] # 安装包 %python.conda uninstall [PACKAGE NAME] # 卸载包其核心逻辑changePythonEnvironment()会把目标环境的bin/python路径通过PythonInterpreter.setPythonExec()注入,随后restartPythonProcess()关闭并重新打开原生解释器,从而让新环境立即生效。执行conda list / env list时,输出会被解析为键值对并用 HTML 表格样式渲染。
%python.docker:Docker 容器内运行 Python
PythonDockerInterpreter.java 允许把 Python 进程放进指定镜像的容器中运行:
%python.docker activate [Repository] %python.docker activate [Repository:Tag] %python.docker activate [Image Id] %python.docker deactivate例如激活官方 TensorFlow 镜像:
%python.docker activate gcr.io/tensorflow/tensorflow:latest激活时它先执行docker pull <image>,随后把 Python 工作目录挂载为/_python_workdir、Zeppelin 安装目录挂载为/_zeppelin,并构造一条docker run -i --rm -v ... -e PYTHONPATH=... <image> <python> /_python_workdir/zeppelin_python.py命令作为新的 pythonExec,再重启 Python 进程。这里同样要求 Docker 能访问宿主机的临时目录,这也是 PythonInterpreter.java 在 macOS 上把java.io.tmpdir强制设为/tmp的原因。
IPython 解释器:将执行委托给 Jupyter 内核
README 的后半部分专门介绍了 IPython 解释器,先看它的需求清单:
You need to install the following python packages to make the IPython interpreter work.
- jupyter 5.x
- IPython
- ipykernel
- grpcio
如果已经安装了 Anaconda,则通常只需额外安装grpc即可(Anaconda 自带 jupyter/IPython/ipykernel)。
架构:jupyter_client 委托 + gRPC 通信
README 的 IPython Architecture 一节给出了与原生解释器截然不同的架构:
Current interpreter delegate the whole work to ipython kernel via
jupyter_client. Zeppelin would launch a python process which host the ipython kernel. Zeppelin interpreter process will communicate with the python process viagrpc. Ideally every feature works in IPython should work in Zeppelin as well.
即 IPython 解释器把全部执行工作委托给真正的 IPython 内核:Zeppelin 启动一个托管 IPython 内核的 Python 进程,JVM 与内核进程之间通过gRPC通信。由于内核本身能力远强于裸 Python REPL,因此在 Jupyter 中可用的功能(magic 方法、代码补全、内联绘图、彩色输出、富文本可视化等)在 Zeppelin 中同样可用。
对照源码,IPythonInterpreter.java 继承了org.apache.zeppelin.jupyter.JupyterKernelInterpreter(来自zeppelin-jupyter模块),gRPC 协议由 ipython.proto 定义——从该类中直接使用的org.apache.zeppelin.interpreter.jupyter.proto.ExecuteRequest/ExecuteResponse/ExecuteStatus即可印证。getRequiredPackagesPredicates()还会额外校验 Python 侧是否安装了ipython与ipykernel,作为内核前置检查的一部分。
此外,IPythonInterpreter 同样保留 Py4J 桥(README 所述动态表单能力延续至此):open()在启动内核后,会通过jupyterKernelClient.block_execute()依次向内核注入 zeppelin_ipython.py(模板中${JVM_GATEWAY_PORT}、${JVM_GATEWAY_ADDRESS}会被替换为真实端口与地址)、zeppelin_context.py,最后执行z = __zeppelin__ = PyZeppelinContext(intp.getZeppelinContext(), gateway)建立z对象。
%python与%python.ipython的关系
模块内存在一个重要的自动降级机制:%python并不是永远使用原生解释器。PythonInterpreter.java 的open()首先尝试获取同组的 IPythonInterpreter,若属性zeppelin.python.useIPython=true(默认值)且 IPython 前置条件(jupyter、grpcio 等)全部满足,就直接用 IPythonInterpreter 替换 PythonInterpreter处理%python段落;否则回退到原生 Python 解释器。因此:
- 环境越简单(只有 python),
%python越可能落到原生解释器; - 环境越完整(装了 IPython 全家桶),
%python越可能获得 Jupyter 级体验,而%python.ipython始终显式使用 IPython。
IPython 侧还支持setAdditionalPythonPath、setAdditionalPythonInitFile等扩展点(供 IPySpark 等子类注入自定义 PYTHONPATH 与初始化脚本),并在setupKernelEnv()中把内置 py4j 加入PYTHONPATH并注入PY4J_GATEWAY_SECRET。
IPython 使用示例
以下是 docs/interpreter/python.md 中给出的典型用法:
%python.ipython # Python 帮助 range? # timeit magic %timeit range(100)%python.ipython %matplotlib inline import matplotlib.pyplot as plt print("hello world") data = [1, 2, 3, 4] plt.figure() plt.plot(data)%python.ipython !pip install pandas!前缀执行 shell 命令、%使用 magic、range?查看帮助,这些都是 Jupyter 用户在 Zeppelin 中可直接复用的能力。仓库自带的教程笔记(notebook/Python Tutorial目录下的1. IPython Basic与2. IPython Visualization Tutorial)提供了更完整的上手示例。
关键配置项
在 Zeppelin 解释器设置界面或%python.conf段落中,可以调整以下配置(完整表格见 docs/interpreter/python.md):
| 属性 | 默认值 | 说明 |
|---|---|---|
zeppelin.python | python | Python 可执行文件路径(python2 或 python3)。若 python 不在$PATH中(如/usr/bin/python),应显式设置 |
zeppelin.python.maxResult | 1000 | z.show()展示 DataFrame 的最大行数 |
zeppelin.python.useIPython | true | 为 true 时,%python在 IPython 可用的情况下自动委派给%python.ipython |
zeppelin.yarn.dist.archives | 空 | Yarn 模式下指定 conda 环境归档文件(本地或 Hadoop 文件系统) |
zeppelin.interpreter.conda.env.name | 空 | Yarn 模式下 conda 环境名,即归档解压后在工作目录中的文件夹名 |
Yarn 集群模式下的 Python 环境管理
README 正文之外,模块文档还覆盖了“在 Yarn 集群中运行 Python 解释器”这一场景(详见 docs/interpreter/python.md)。由于 Yarn 集群是多节点分布式环境,Python 解释器可能被调度到任意节点,逐节点预装环境不现实,因此推荐的方案是用conda 打包环境并随任务分发(仅 IPython 模式支持):
- 编写
python_3_env.yml,包含python=3.9、jupyter、grpcio、protobuf、numpy、pandas、pandasql、hvplot、pyarrow等包,然后执行conda env create -f python_3_env.yml; - 使用
conda pack -n python_3_env把环境打包为 tar 归档; - 在
%python.conf中开启 Yarn 启动器并指定归档与环境名:
%python.conf zeppelin.interpreter.launcher yarn zeppelin.yarn.dist.archives /home/hadoop/python_3_env.tar.gz#environment zeppelin.interpreter.conda.env.name environment其中zeppelin.yarn.dist.archives中的#environment是归档解压后的文件夹名,它必须与zeppelin.interpreter.conda.env.name保持一致;PythonInterpreter.java 的getPythonExec()正是依据该属性拼接出{env.name}/bin/python来启动 Python 的。
快速体验与进阶资源
- 想零配置体验,可以使用 Zeppelin Docker 镜像(scripts/docker/zeppelin-interpreter/Dockerfile 及其配套的 env_python_3.yml 已内置 miniconda 与 IPython 前置依赖,
%python会直接走 IPython),随后打开http://localhost:8080,直接运行notebook/Python Tutorial目录下的教程笔记; - 模块完整的用户级使用说明见 docs/interpreter/python.md;
- 想深入源码,可以从 PythonInterpreter.java(Java 侧生命周期)、zeppelin_python.py(Python 侧主循环)与 IPythonInterpreter.java(IPython 桥接)三处入手,配合 BasePythonInterpreterTest.java 等测试用例验证各条链路的行为。
小结
Apache Zeppelin 的 Python 模块通过“JVM 侧解释器 + 独立 Python 子进程 + Py4J 网关 +(可选)Jupyter 内核”的分层架构,在保持语言隔离的同时实现了动态表单、代码补全、matplotlib 内联绘图、Pandas SQL、Conda/Docker/Yarn 环境管理等一系列生产级能力。其核心要点可以归纳为:原生解释器以ProcessBuilder启动带-i -u的 Python 进程并借助 Py4J 完成双向调用与输出转发;中断执行通过kill -SIGINT <pid>实现并在 Python 侧恢复默认信号处理器;IPython 解释器则将执行委托给 Jupyter 内核并经 gRPC 通信,在 Zeppelin 中复刻 Jupyter 的完整体验。对于希望二次开发或深入调优该解释器的工程师,python/README.md 的架构说明与本文梳理的源码链路可以互为印证、作为可靠的起点。
- 数据分析
- 数据可视化
- 大数据
- 后端
- 前端
- 任务调度
【免费下载链接】zeppelin
Web-based notebook that enables>项目地址:https://gitcode.com/gh_mirrors/zeppe/zeppelin
相关推荐
OmniVoice 训练数据准备完整指南:JSONL 清单、音频 Token 提取与 WebDataset 分片
OmniVoice 训练数据准备完整指南:JSONL 清单、音频 Token 提取与 WebDataset 分片 OmniVoice 是一款面向 600+ 语言
数据分析数据可视化大数据后端前端任务调度OptiScaler:让非N卡用上DLSS/FSR/XeSS的开源超分中间件
OptiScaler:让非N卡用上DLSS/FSR/XeSS的开源超分中间件 游戏菜单里DLSS选项是灰的,显卡是AMD的,帧率就上不去。OptiScaler是
图形学游戏开发Vue-handsontable-official 终极指南:如何在 Vue 项目中快速集成强大的电子表格组件
Vue handsontable official 终极指南:如何在 Vue 项目中快速集成强大的电子表格组件 想要在 Vue 项目中快速集成功能强大的电子表格