如何获取当前的IPython Notebook名称

Too*_*ppe 63 python ipython

我正在尝试在运行IPython笔记本时获取当前的NoteBook名称.我知道我可以在笔记本的顶部看到它.我喜欢什么样的东西

currentNotebook = IPython.foo.bar.notebookname()
Run Code Online (Sandbox Code Playgroud)

我需要在变量中获取名称.

jfb*_*jfb 35

我有以下适用于IPython 2.0.我观察到,笔记本电脑的名称被存储为属性的值'data-notebook-name'<body>页面的标签.因此,这个想法首先要求Javascript检索属性 - 由于魔法,可以从codecell调用javascripts %%javascript.然后可以通过调用Python Kernel来访问Javascript变量,并使用一个设置Python变量的命令.由于最后一个变量是从内核中获知的,因此也可以在其他单元中访问它.

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

来自Python代码单元

print(theNotebook)
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

然后,从ipython单元格,

In [11]: print(theNotebook)
Out [11]: HowToGetTheNameOfTheNoteBookSolBis
Run Code Online (Sandbox Code Playgroud)

与第一种解决方案相反,笔记本名称的修改会立即更新,无需刷新笔记本.

  • 也可以使用应用于javascript对象的显示方法从python中调用javascript,例如`def getname():display(Javascript('theNotebook ="+"\'"+ IPython.notebook.notebook_name + "\"");'))` (6认同)
  • 要在没有 JS 欺骗的情况下获取笔记本路径:`globals()['_dh'][0]` (2认同)

Mah*_*dar 29

添加到以前的答案,

获取笔记本名称在单元格中运行以下内容:

%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')
Run Code Online (Sandbox Code Playgroud)

这将获取nb_name中的文件名

然后,要获得完整路径,您可以在单独的单元格中使用以下内容:

import os
nb_full_path = os.path.join(os.getcwd(), nb_name)
Run Code Online (Sandbox Code Playgroud)

  • 出于某种原因,这只有在我"手动"运行javascript单元格时才有效.如果我运行完整的笔记本电脑,第二个单元格失败 知道为什么吗? (7认同)
  • 名称错误:名称“nb_name”未定义 (6认同)
  • 为什么我们实际上需要javascript?没有更多的本土? (3认同)
  • Jupyter Lab 失败:“Javascript 错误:IPython 未定义” (3认同)
  • 它仅适用于手动执行单个单元格...Javascript 调用是异步的,并且不能保证在 python 开始运行包含此笔记本名称的使用者的另一个单元格之前完成...导致“NameError”。 (2认同)

Igu*_*aut 25

正如已经提到的,你可能不是真的应该这样做,但我确实找到了办法.这是一个火红的黑客,所以不要依赖于此:

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
Run Code Online (Sandbox Code Playgroud)

我更新了我的答案,包括一个在IPython 2.0中"工作"的解决方案,至少通过一个简单的测试.如果有多个笔记本连接到同一内核,可能无法保证给出正确答案.

  • 一些更新:而不是`来自IPython.lib导入内核`现在它只是来自IPython导入内核`.而不是在词典中使用键'name',使用键'path' (2认同)

Zep*_*lag 25

在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);
Run Code Online (Sandbox Code Playgroud)

然后显示它:

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)
Run Code Online (Sandbox Code Playgroud)

运行第一个Javascript单元格不会产生任何输出.运行第二个Python单元格会产生类似于:

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb
Run Code Online (Sandbox Code Playgroud)

  • 这很干净.你如何从Python函数调用Javascript代码呢? (4认同)
  • 我收到“Javascript 错误:IPython 未定义”。如何加载 javascript 的 IPython (4认同)
  • 这是相对路径而非完整路径 (3认同)

Bil*_*ill 20

ipyparams包可以做到这一点很容易地。

import ipyparams
currentNotebook = ipyparams.notebook_name
Run Code Online (Sandbox Code Playgroud)

  • 我找到了包 [ipynbname](https://pypi.org/project/ipynbname/) 的解决方案 (9认同)
  • @bill,您好,我在最近的 jupyter 笔记本版本上尝试了这个解决方案,但我没有设法让它工作。我创建了一篇文章[[此处](/sf/ask/4397072291/)] (3认同)
  • 这似乎是比顶部接受的答案更好的答案。 (2认同)

P.T*_*eli 16

我似乎无法评论,所以我必须将此作为答案发布.

@iguananaut接受的解决方案和@mbdevpl的更新似乎不适用于最新版本的Notebook.我修好了它,如下图所示.我在Python v3.6.1 + Notebook v5.0.0以及Python v3.6.5和Notebook v5.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
Run Code Online (Sandbox Code Playgroud)

正如文档字符串中所述,只有在没有身份验证或身份验证是基于令牌的情况下,这才有效.

请注意,正如其他人所报告的那样,基于Javascript的方法在执行"运行所有单元格"时似乎不起作用(但在"手动"执行单元格时有效),这对我来说是一个交易破坏者.


小智 8

这是另一个黑客解决方案,因为我的笔记本服务器可以更改。基本上,您打印一个随机字符串,保存它,然后在工作目录中搜索包含该字符串的文件。需要 while 是因为 save_checkpoint 是异步的。

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)
Run Code Online (Sandbox Code Playgroud)


138*_*pen 7

只需使用ipynbname,这很实用

#! pip install ipynbname

import ipynbname
nb_fname = ipynbname.name()
nb_path = ipynbname.path()
print(f"{nb_fname=}")
print(f"{nb_path=}")
Run Code Online (Sandbox Code Playgroud)

我在/sf/answers/4613523141/中找到了这个


tel*_*tel 6

Jupyterlab 中还没有真正的方法可以做到这一点。但截至 2021 年 8 月,有一种官方方式正在积极讨论/开发中:

https://github.com/jupyter/jupyter_client/pull/656

与此同时,到达api/sessionsREST 端点jupyter_server似乎是最好的选择。这是该方法的清理版本:

from jupyter_server import serverapp
from jupyter_server.utils import url_path_join
from pathlib import Path
import re
import requests

kernelIdRegex = re.compile(r"(?<=kernel-)[\w\d\-]+(?=\.json)")

def getNotebookPath():
    kernelId = kernelIdRegex.search(get_ipython().config["IPKernelApp"]["connection_file"])[0]
    
    for jupServ in serverapp.list_running_servers():
        for session in requests.get(url_path_join(jupServ["url"], "api/sessions"), params={"token": jupServ["token"]}).json():
            if kernelId == session["kernel"]["id"]:
                return Path(jupServ["root_dir"]) / session["notebook"]['path']
Run Code Online (Sandbox Code Playgroud)

已测试与

python==3.9
jupyter_server==1.8.0
jupyterlab==4.0.0a7
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您使用的是 Visual Studio Code:

import IPython ; IPython.extract_module_locals()[1]['__vsc_ipynb_file__']
Run Code Online (Sandbox Code Playgroud)