現在のIPython / JupyterNotebook名を取得するにはどうすればよいですか


87

IPythonノートブックを実行しているときに現在のNoteBook名を取得しようとしています。私はそれがノートブックの上部に見えることを知っています。私が何を求めているのか

currentNotebook = IPython.foo.bar.notebookname()

変数で名前を取得する必要があります。


あなたはそれで何をしようとしていますか?設計上、カーネル(コードを実行するビット)はフロントエンド(ノートブックを開くビット)を認識していません。
トーマスK

7
こんにちは。nbconvertで使用して、ノートブックからラテックス/ PDFへの作成プロセスを自動化したいです。私のノートブックはリモートで実行されます。クラス終了後、生徒は結果のPDFバージョンをダウンロードできます。
Tooblippe 2012

1
P.Toccaceliの回答は、最近のバージョンのJupyterLab(1.1.4)(ノートブック5.6.0)でうまく機能し、JavaScriptを必要としません。
joelostblom


一部は仕事を行なったし、PIPパッケージを作っ:pypi.org/project/ipynbname インストールでpip install ipynbname
NeoTT

回答:


26

すでに述べたように、あなたはおそらくこれを実際に行うことができるはずではありませんが、私は方法を見つけました。それは燃えるようなハックですが、これにまったく依存しないでください:

import json
import os
import urllib2
import IPython
from IPython.lib import kernel
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]

# Updated answer with semi-solutions for both IPython 2.x and IPython < 2.x
if IPython.version_info[0] < 2:
    ## Not sure if it's even possible to get the port for the
    ## notebook app; so just using the default...
    notebooks = json.load(urllib2.urlopen('http://127.0.0.1:8888/notebooks'))
    for nb in notebooks:
        if nb['kernel_id'] == kernel_id:
            print nb['name']
            break
else:
    sessions = json.load(urllib2.urlopen('http://127.0.0.1:8888/api/sessions'))
    for sess in sessions:
        if sess['kernel']['id'] == kernel_id:
            print sess['notebook']['name']
            break

少なくとも簡単なテストでIPython2.0で「機能する」ソリューションを含めるように回答を更新しました。同じカーネルに複数のノートブックが接続されている場合など、正しい答えが得られるとは限りません。


connection_file_path = kernel.get_connection_file()は機能しなくなり、filenameはargが必要です。
Purrell 2013年

2
いくつかの更新:from IPython.lib import kernel今ではなく、ただfrom IPython import kernelです。また、辞書でキー「名前」を使用する代わりに、キー「パス」を使用します
Tristan Reid

1
回答者自身が宣伝しているように、この回答は最新のIPythonでは機能しません。Python3.5のIPython4.2.0
mbdevpl 2016

1
バージョン4.3.0以降、認証トークンを提供する必要があります。これは、を使用して取得できますnotebook.notebookapp.list_running_servers()
2017

1
複数のサーバーを実行している場合は、カーネルの親プロセスがリッスンしているポートを確認できます。これにより、接続するサーバーがわかります(または、すべてのローカルJupyterサーバーに接続して、カーネルを実行しているサーバーを確認できます)。
2017

41

IPython2.0で動作する次のものがあります。ノートブックの名前が属性の値としてページのタグに格納されていることを確認し'data-notebook-name'ました<body>。したがって、アイデアは最初にJavascriptに属性を取得するように依頼すること%%javascriptです。魔法のおかげでjavascriptsをコードセルから呼び出すことができます。次に、Python変数を設定するコマンドを使用して、Pythonカーネルを呼び出してJavascript変数にアクセスすることができます。この最後の変数はカーネルから認識されているため、他のセルからもアクセスできます。

%%javascript
var kernel = IPython.notebook.kernel;
var body = document.body,  
    attribs = body.attributes;
var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'";
kernel.execute(command);

Pythonコードセルから

print(theNotebook)

Out []:HowToGetTheNameOfTheNoteBook.ipynb

このソリューションの欠点は、ノートブックのタイトル(名前)を変更すると、この名前がす​​ぐに更新されないように見え(おそらく何らかのキャッシュがある)、ノートブックにアクセスするためにノートブックをリロードする必要があることです。新しい名前。

[編集]振り返ってみると、より効率的な解決策は、<body>タグの代わりにノートブックの名前の入力フィールドを探すことです。ソースを調べると、このフィールドのIDは「notebook_name」であるようです。次に、この値をaでキャッチしdocument.getElementById()、上記と同じアプローチに従うことができます。コードは、まだjavascriptマジックを使用してなります

%%javascript
var kernel = IPython.notebook.kernel;
var thename = window.document.getElementById("notebook_name").innerHTML;
var command = "theNotebook = " + "'"+thename+"'";
kernel.execute(command);

次に、ipythonセルから、

In [11]: print(theNotebook)
Out [11]: HowToGetTheNameOfTheNoteBookSolBis

最初の解決策とは異なり、ノートブックの名前の変更はすぐに更新され、ノートブックを更新する必要はありません。


何かを見逃したかもしれませんが、Pythonからjavascriptコードをどのように呼び出しますか?
Artjom B. 2014

7
次のようなjavascriptオブジェクトに適用されたdisplayメソッドを使用してPython内からjavascriptを呼び出すこともできますdef getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
Jakob

ノートブックのパスを取得するためにこれを変更するにはどうすればよいですか?
Pedro M Duarte

@PedroMDuarte:上記のスクリプトの「thename」のjavascriptでIPython.notebook.notebook_pathを使用して、その値を取得できます。
Tristan Reid

1
JSのトリックなしでノートブックのパスを取得するには:globals()['_dh'][0]
生殖

38

以前の回答に追加して、

ノートブック名を取得するには、セルで次のコマンドを実行します。

%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

これにより、nb_nameのファイル名が取得されます

次に、フルパスを取得するには、別のセルで次を使用できます。

import os
nb_full_path = os.path.join(os.getcwd(), nb_name)

1
使用してIPython.notebook.notebook_nameこれを使用して行うことができます%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
JFBを

10
何らかの理由で、これはjavascriptセルを「手動で」実行した場合にのみ機能します。ノートブック全体を実行すると、2番目のセルが失敗します。理由は何ですか?
ピエールアントワーヌ

何らかの理由で、変数がjavascriptから変更され、同じ呼び出しで純粋なpythonからアクセスされた場合、pythonバージョンは更新を認識せず、javascriptバージョンも置き換えます。したがって、javascriptセルを一番上に移動して実行し、「Cell> RunAllBellow」を使用することもできます。
Mahmoud Elagdar 2018年

2
なぜ実際にJavaScriptが必要なのですか?これ以上ネイティブなものはありませんか?
マタンスター2018

2
Jupyterラボで失敗:Javascript Error: IPython is not defined
magicrebirth

27

Jupyter 3.0では、次のように動作します。ここでは、ノートブック名だけでなく、Jupyterサーバー上のパス全体を示しています。

NOTEBOOK_FULL_PATH現在のノートブックフロントエンドにを保存するには:

%%javascript
var nb = IPython.notebook;
var kernel = IPython.notebook.kernel;
var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'";
kernel.execute(command);

次にそれを表示するには:

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)

最初のJavascriptセルを実行しても、出力は生成されません。2番目のPythonセルを実行すると、次のようになります。

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb

4
これはとてもきれいです。では、Python関数からJavascriptコードをどのように呼び出しますか?
ルーカス2015年

うーん...多分その場合、コロンとそれに続くポート番号をポートに追加する必要がありますか?
Zephaniah Grunschlag 2016

3
これはフルパスではなく相対パスです
Ivelin 2016年

これには、の設定も含まれませんc.NotebookApp.notebook_dir
sappjw

4
取得していJavascript Error: IPython is not definedます。どのように私はjavascriptのためにIPythonを読み込むことができます
ZOZO

26

コメントできないようですので、回答として投稿する必要があります。

@iguananautによって受け入れられた解決策と@mbdevplによる更新は、ノートブックの最近のバージョンでは機能していないようです。以下のように修正しました。Python v3.6.1 + Notebookv5.0.0とPythonv3.6.5およびNotebookv5.5.0で確認しました。

from notebook import notebookapp
import urllib
import json
import os
import ipykernel

def notebook_path():
    """Returns the absolute path of the Notebook or None if it cannot be determined
    NOTE: works only when the security is token-based or there is also no password
    """
    connection_file = os.path.basename(ipykernel.get_connection_file())
    kernel_id = connection_file.split('-', 1)[1].split('.')[0]

    for srv in notebookapp.list_running_servers():
        try:
            if srv['token']=='' and not srv['password']:  # No token and no password, ahem...
                req = urllib.request.urlopen(srv['url']+'api/sessions')
            else:
                req = urllib.request.urlopen(srv['url']+'api/sessions?token='+srv['token'])
            sessions = json.load(req)
            for sess in sessions:
                if sess['kernel']['id'] == kernel_id:
                    return os.path.join(srv['notebook_dir'],sess['notebook']['path'])
        except:
            pass  # There may be stale entries in the runtime directory 
    return None

docstringに記載されているように、これは認証がないか、認証がトークンベースの場合にのみ機能します。

他の人からも報告されているように、Javascriptベースの方法は、「すべてのセルを実行」を実行すると機能しないようです(ただし、セルを「手動で」実行すると機能します)。これは私にとっては大きな問題でした。


このためのライブラリはありますか?
マタンスター2018年

Javascriptメソッドの失敗は、私にとっても大きな問題でした。この代替案を投稿していただきありがとうございます。
機智

srv ['notebook_dir']をfromjupyter_core.paths importjupyter_config_dirに置き換える必要があります。traitlets.configからimportConfig; c = Config(); file_path = os.path.join(jupyter_config_dir()、 'jupyter_notebook_config.py'); exec(open(file_path).read()); ROOT_DIR = C [ 'FileContentsManager'] [ 'ROOT_DIR']
デイブバビット

15

ipyparamsのパッケージはかなり簡単にこれを行うことができます。

import ipyparams
currentNotebook = ipyparams.notebook_name

1
これは、一番上で受け入れられているものよりも良い答えのようです。
アレハンドロ

1

Jupyter Notebookサーバーのホスト、ポート、および認証トークンがある場合、これは機能するはずです。それはこの答えに基づいています

import os
import json
import posixpath
import subprocess
import urllib.request
import psutil

def get_notebook_path(host, port, token):
    process_id = os.getpid();
    notebooks = get_running_notebooks(host, port, token)
    for notebook in notebooks:
        if process_id in notebook['process_ids']:
            return notebook['path']

def get_running_notebooks(host, port, token):
    sessions_url = posixpath.join('http://%s:%d' % (host, port), 'api', 'sessions')
    sessions_url += f'?token={token}'
    response = urllib.request.urlopen(sessions_url).read()
    res = json.loads(response)
    notebooks = [{'kernel_id': notebook['kernel']['id'],
                  'path': notebook['notebook']['path'],
                  'process_ids': get_process_ids(notebook['kernel']['id'])} for notebook in res]
    return notebooks

def get_process_ids(name):
    child = subprocess.Popen(['pgrep', '-f', name], stdout=subprocess.PIPE, shell=False)
    response = child.communicate()[0]
    return [int(pid) for pid in response.split()]

使用例:

get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')

0

私のノートブックサーバーは変更される可能性があるため、さらに別のハッキーなソリューション。基本的に、ランダムな文字列を印刷して保存し、その文字列を含むファイルを作業ディレクトリで検索します。save_checkpointは非同期であるため、whileが必要です。

from time import sleep
from IPython.display import display, Javascript
import subprocess
import os
import uuid

def get_notebook_path_and_save():
    magic = str(uuid.uuid1()).replace('-', '')
    print(magic)
    # saves it (ctrl+S)
    display(Javascript('IPython.notebook.save_checkpoint();'))
    nb_name = None
    while nb_name is None:
        try:
            sleep(0.1)
            nb_name = subprocess.check_output(f'grep -l {magic} *.ipynb', shell=True).decode().strip()
        except:
            pass
    return os.path.join(os.getcwd(), nb_name)

0

一度に複数のセルを実行すると、すべてのJsonベースのソリューションが失敗します。これは、実行が終了するまで結果の準備ができていないためです(スリープを使用したり、いつでも待機したりする必要はありません。自分で確認してください。ただし、カーネルを再起動することを忘れないでください)。すべてのテストを実行します)

以前の解決策に基づいて、これにより、他のコードの途中に配置する必要がある場合に備えて、%%マジックの使用が回避されます。

from IPython.display import display, Javascript

# can have comments here :)
js_cmd = 'IPython.notebook.kernel.execute(\'nb_name = "\' + IPython.notebook.notebook_name + \'"\')'
display(Javascript(js_cmd))

Python 3の場合、@ Iguananautの回答に基づいて、最新のPythonおよび場合によっては複数のサーバー用に更新された以下が機能します。

import os
import json
try:
    from urllib2 import urlopen
except:
    from urllib.request import urlopen
import ipykernel

connection_file_path = ipykernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]    
    
running_servers = !jupyter notebook list
running_servers = [s.split('::')[0].strip() for s in running_servers[1:]]
nb_name = '???'
for serv in running_servers:
    uri_parts = serv.split('?')
    uri_parts[0] += 'api/sessions'
    sessions = json.load(urlopen('?'.join(uri_parts)))
    for sess in sessions:
        if sess['kernel']['id'] == kernel_id:
            nb_name = os.path.basename(sess['notebook']['path'])
            break
    if nb_name != '???':
        break
print (f'[{nb_name}]')
    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.