LoginSignup
3
1

More than 5 years have passed since last update.

JupyterをRESTから操作する

Posted at

はじめに

JupyterNotebookはブラウザで操作できるので、普通はRESTで操作できる必要はないです。

個人用の備忘録なのですが、こんなのが役に立つのは、Jupyterを使ったシステムを作っているか、
それらの保守等で、自動構築やテスト自動化などが必要な人たちですね。
なんて、マニアックなんだ。

前提

まず、Jupyter Notebook の バージョンは 5.7.2 となる。
色々試してみたが、どうにもパスワード認証がうまくいかなくて、token で動かすとうまくいった。

トークンを取ってくる

token とは、Security in the Jupyter notebook serverのページに登場する token= の後に続く文字列の事です。

[I 11:59:16.597 NotebookApp] The Jupyter Notebook is running at:
http://localhost:8888/?token=c8de56fa4deed24899803e93c227592aef6538f93025fe01

ファイルの一覧

token指定の所が肝。
この指定ができれば、あとはAPIの流儀に従ってパラメータやパス指定するだけ、とても簡単です。

from __future__ import print_function
from __future__ import unicode_literals
import argparse
import json
import requests

def main():
    """main."""
    parser = argparse.ArgumentParser()
    parser.add_argument('base_url', help='base_url')
    parser.add_argument('token', help='token')
    parser.add_argument('relpath', nargs='?', default='/', help='relative path')
    args = parser.parse_args()

    headers = {
        'Authorization': 'token %s' % args.token,
        'Content-Type': 'application/json'
    }
    resp = requests.get(
        '{}/api/contents{}'.format(args.base_url, args.relpath),
        headers=headers
    )
    print("{}".format(json.dumps(resp.json(), indent=4)))

if __name__ == '__main__':
    main()

ちなみに、パスワードを使おうとして 'Authorization': 'Basic %' … みたくやったのですが、
403 地獄から逃れられず、レスポンスは json でなくて html のページに飛ばされた。

アップロード

  • XSRF のエラーが出る場合は、requests でセションで cookie とか持ちまわるように小細工が必要。
  • 画像とかを送りたいときは、 base64 で埋め込んでやれば良い
  • URLの相対パス指定が肝でファイルやディレクトリがないと失敗する
    そういう意味で、パラメータ側の name とか path の存在意義がいまいちわからず
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import json
import requests

def main():
    """main."""
    parser = argparse.ArgumentParser()
    parser.add_argument('base_url', help='token')
    parser.add_argument('token', help='token')
    parser.add_argument('relpath', help='relative path ... ex. /foo/bar.txt')
    args = parser.parse_args()

    api_url = '{}/api/contents{}'.format(args.base_url, args.relpath)
    headers = {
        'Authorization': 'token %s' % args.token,
        'Content-Type': 'application/json'
    }
    req_body = {
        'name': 'bar.txt',
        'path': '.',
        'type': 'file',
        'format': 'text',
        'content': 'foo'
    }
    resp = requests.put(
        api_url,
        json.dumps(req_body).encode("utf-8"),
        headers=headers
    )
    if resp.headers.get('Content-Type').startswith('application/json'):
        print("{}".format(json.dumps(resp.json(), indent=4)))
    print("")

if __name__ == '__main__':
    main()

参考

  • Security in the Jupyter notebook server — Jupyter Notebook 5.7.4
    token の取り方とか。
  • API
    • Jupyter Notebook Server API
      The schema is here と書かれているあたりをみれば何となく分かる。もし、自由に好きなパッケージをインストールできる状況下にあれば、 requests を使わなくても、Swagger (Open API)で生成してクライアントI/Fを配備しても良いですけどね。
    • Contents API
  • Cookie passing for Jupyter Notebook APIs #1431
    バージョンや環境によっては、X-XSRF-Tokenをいれないと弾かれることがある。クロスサイト リクエスト フォージェリ (CSRF/XSRF) の対策で、クロスサイトかどうかを判別するトークンをいれないといけないとか何とか。
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1