【问题标题】:Interact with Jupyter Notebooks via API通过 API 与 Jupyter Notebooks 交互
【发布时间】:2019-06-25 19:37:57
【问题描述】:

问题:我想通过 Jupyter API 从另一个应用程序与 Jupyter 交互,特别是我想至少从应用程序运行我的笔记本(对我来说完美的变体是在运行它之前编辑一些段落)。我已经阅读了API documentation,但没有找到我需要的内容。

我为此目的使用了 Apache Zeppelin,它们具有相同的结构(笔记本和段落)。

有人将 Jupyter 用于我刚才描述的目的吗?

【问题讨论】:

标签: python jupyter-notebook jupyter remote-access apache-zeppelin


【解决方案1】:

忽略使用 Jupyter API 是否是问题的最佳解决方案(问题中没有明确描述),下面的代码可以满足您的要求:它将通过 http 远程执行 Jupyter 笔记本并获得一些结果。它还没有准备好生产,它更像是一个如何完成的例子。没有用产生大量输出的单元对其进行测试 - 认为它需要调整。

您还可以通过更改代码数组以编程方式更改/编辑代码。

您需要根据您的配置更改 notebook_path、base 和 headers,详情请参阅代码。

import json
import requests
import datetime
import uuid
from pprint import pprint
from websocket import create_connection

# The token is written on stdout when you start the notebook
notebook_path = '/Untitled.ipynb'
base = 'http://localhost:9999'
headers = {'Authorization': 'Token 4a72cb6f71e0f05a6aa931a5e0ec70109099ed0c35f1d840'}

url = base + '/api/kernels'
response = requests.post(url,headers=headers)
kernel = json.loads(response.text)

# Load the notebook and get the code of each cell
url = base + '/api/contents' + notebook_path
response = requests.get(url,headers=headers)
file = json.loads(response.text)
code = [ c['source'] for c in file['content']['cells'] if len(c['source'])>0 ]

# Execution request/reply is done on websockets channels
ws = create_connection("ws://localhost:9999/api/kernels/"+kernel["id"]+"/channels",
     header=headers)

def send_execute_request(code):
    msg_type = 'execute_request';
    content = { 'code' : code, 'silent':False }
    hdr = { 'msg_id' : uuid.uuid1().hex, 
        'username': 'test', 
        'session': uuid.uuid1().hex, 
        'data': datetime.datetime.now().isoformat(),
        'msg_type': msg_type,
        'version' : '5.0' }
    msg = { 'header': hdr, 'parent_header': hdr, 
        'metadata': {},
        'content': content }
    return msg

for c in code:
    ws.send(json.dumps(send_execute_request(c)))

# We ignore all the other messages, we just get the code execution output
# (this needs to be improved for production to take into account errors, large cell output, images, etc.)
for i in range(0, len(code)):
    msg_type = '';
    while msg_type != "stream":
        rsp = json.loads(ws.recv())
        msg_type = rsp["msg_type"]
    print(rsp["content"]["text"])

ws.close()

制作此代码的有用链接(如果您想了解更多信息,我建议您阅读):

请注意,还有 https://jupyter-client.readthedocs.io/en/stable/index.html,但据我所知,它不支持 HTTP 作为传输方式。

作为参考,这适用于 notebook-5.7.4,不确定其他版本。

【讨论】:

  • 很棒的代码 sn-p!作为一个快速说明,如果您不想检查控制台输出以查找 jupyter 令牌是什么,您可以在使用这样的 env var 启动笔记本时手动指定令牌:$ JUPYTER_TOKEN=this-is-my-token jupyter notebook
  • 当我尝试这个时,while msg_type != "stream" 似乎是一个无限循环。但是,我可以看到execute_reply 类型的消息,但这些消息中似乎没有代码输出。任何想法为什么会这样?
  • 你为什么要附加 - /api/kernels,如果我附加 /api/kernels 部分,我可以从基本 URL 访问浏览器上的笔记本,但找不到页面。
  • @Infinite :也许提及您使用的笔记本版本会有所帮助。答案大约有 2 年的历史,在答案中提到的版本 (5.7.4) 和今天大约有 20 个新版本之间 - 事情可能已经改变了。
  • 如何保证'code'中的变量会被保留为全局变量?我尝试在使用代码镜像的烧瓶应用程序中使用上述代码,但单元格一中定义的变量未保留在单元格二中。我们如何确保单元格一中定义的变量在单元格二中也可用?
【解决方案2】:

我认为在你的情况下使用远程 Jupyter Notebook 是过度设计的。

我看到好的方法是通过良好的日志记录将必要的参数传递给 python 程序。

【讨论】:

    【解决方案3】:

    @vladmihaisima 扩展代码

    from websocket import create_connection, WebSocketTimeoutException
    
            while msg_type != "stream":
                try:
                    rsp = json.loads(ws.recv())
                    print(rsp["msg_type"])
                    print(rsp)
                    msg_type = rsp["msg_type"]
                    if msg_type == "error":
                        raise Exception(rsp['content']['traceback'][0])
                except WebSocketTimeoutException as _e:
                    print("No output")
                    return
    

    【讨论】:

      猜你喜欢
      • 2019-04-02
      • 1970-01-01
      • 2023-03-14
      • 2017-01-11
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 2021-06-13
      相关资源
      最近更新 更多