How do I get the current IPython / Jupyter Notebook name
Asked Answered
H

18

124

I am trying to obtain the current NoteBook name when running the IPython notebook. I know I can see it at the top of the notebook. What I am after something like

currentNotebook = IPython.foo.bar.notebookname()

I need to get the name in a variable.

Holleyholli answered 22/9, 2012 at 13:9 Comment(7)
What are you trying to do with it? By design, the kernel (the bit that runs code) doesn't know about the frontend (the bit that opens notebooks).Alby
Hi, I want to use it with nbconvert to automate the notebook to latex/pdf creation process. My notebooks run remotely. after a class students can download a pdf version of their results.Holleyholli
P.Toccaceli's answer works well with recent versions of JupyterLab (1.1.4) (notebook 5.6.0) and does not require javascript.Td
related: github.com/jupyter/notebook/issues/1000#issuecomment-359875246Artemas
Some did the work and made a pip package: pypi.org/project/ipynbname install by pip install ipynbnamePratte
Yes ipynbname is now working with jupyter 3 (more details here)Conics
ipynbname did not work on jupyter 4 though.Refrigerate
P
32

As already mentioned you probably aren't really supposed to be able to do this, but I did find a way. It's a flaming hack though so don't rely on this at all:

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

I updated my answer to include a solution that "works" in IPython 2.0 at least with a simple test. It probably isn't guaranteed to give the correct answer if there are multiple notebooks connected to the same kernel, etc.

Perseverance answered 24/10, 2012 at 18:35 Comment(8)
connection_file_path = kernel.get_connection_file() doesn't work anymore, filename is required arg.Ioannina
This worked fine for me on IPython.__version__ of '0.13.2' and I didnot have to specify a filename for the kernel.get_connection_file()Disobedient
Some updates: Instead of from IPython.lib import kernel now it's just from IPython import kernel. Also instead of using the key 'name' in the dictionaries, use the key 'path'Hodosh
As advertised by the answerer himself, this answer doesn't work for latest IPython. I've created a version that seems to work with IPython 4.2.0 in Python 3.5: gist.github.com/mbdevpl/f97205b73610dd30254652e7817f99cbShouldst
As of version 4.3.0, you need to provide an auth token. This can be retrieved using notebook.notebookapp.list_running_servers().Illaudable
If you have multiple servers running, you can check what port the kernel's parent process is listening on, which should tell you which server to connect to (or you can just connect to every local Jupyter server and check which is running your kernel).Illaudable
if you have multiple servers running, you can list all of them using !jupyter notebook list This will give all running notebooks and then use the one with the correct pwd, or just check them allTali
This may be outdated, another answer in this thread below shows that not only it is fine but fairly easy to get the name of the current notebook from within itself.Scherman
L
53

adding to previous answers,

to get the notebook name run the following in a cell:

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

this gets you the file name in nb_name

then to get the full path you may use the following in a separate cell:

import os
nb_full_path = os.path.join(os.getcwd(), nb_name)
Limiting answered 16/6, 2017 at 12:17 Comment(14)
Using IPython.notebook.notebook_name this can be done using %%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"') Horatia
For some reason this only work if I run the javascript cell "manually". If I run the full notebook the second cell fails. Any idea why?Ichthyic
I guess for some reason, if a variable is modified from javascript then accessed from pure python in the same call, the python version doesn't see the update and also replaces the javascript version. So I guess you may move the javascript cell to the top, run it, then use "Cell>Run All Bellow".Limiting
Why do we need javascript actually? nothing more native?Sieber
Let me guess that your python code is sent to a kernel running in the terminal where you launched Jupyter. That kernel doesn't know much about your notebook and the only solution I found so far is using Javascript. There's however a way to run Javascript using iPython, see the following two lines: from IPython.display import Javascript as d_js; d_js("IPython.notebook.kernel.execute('nb_name = \"' + IPython.notebook.notebook_name + '\"')")Limiting
NameError: name 'nb_name' is not definedCe
Did the JavaScript part run without errors before you ran the Python part?Limiting
@MahmoudElagdar, "Cell>Run All Bellow" doesn't seem an option when remotely running the notebook from another notebook with %runMendive
@MahmoudElagdar, the d_js method works in a given notebook when called by a wrapper function, say notebook_name() that returns nb_name. However, it throws NameError: name 'nb_name' is not defined when %run is used to evaluate the notebook containing notebook_name(). Any ideas?Mendive
@Mendive perhaps P.Toccaceli's post can help? the problem is you can't set the variable nb_name and use it in the same run because of the way javascript calls are implemented so you have to split it into two runsLimiting
@MahmoudElagdar Can we convert the Javascript part to python? I tried from IPython import notebook print(IPython.notebook.notebook_name) But it's throwing error: cannot import name 'notebook'. Please help. ThanksCalci
Fails on Jupyter Lab: Javascript Error: IPython is not definedKaryoplasm
It's good only for manual execution of a single cell... Javascript calls are async and not guaranteed to complete before python starts running another cell that contains the consumer of this notebook name... resulting in NameError.Evidential
@Evidential The async idea is interesting, IDK I tried adding a sleep and still didn't work. Maybe try P.Toccaceli's solutionLimiting
H
42

I have the following which works with IPython 2.0. I observed that the name of the notebook is stored as the value of the attribute 'data-notebook-name' in the <body> tag of the page. Thus the idea is first to ask Javascript to retrieve the attribute --javascripts can be invoked from a codecell thanks to the %%javascript magic. Then it is possible to access to the Javascript variable through a call to the Python Kernel, with a command which sets a Python variable. Since this last variable is known from the kernel, it can be accessed in other cells as well.

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

From a Python code cell

print(theNotebook)

Out[ ]: HowToGetTheNameOfTheNoteBook.ipynb

A defect in this solution is that when one changes the title (name) of a notebook, then this name seems to not be updated immediately (there is probably some kind of cache) and it is necessary to reload the notebook to get access to the new name.

[Edit] On reflection, a more efficient solution is to look for the input field for notebook's name instead of the <body> tag. Looking into the source, it appears that this field has id "notebook_name". It is then possible to catch this value by a document.getElementById() and then follow the same approach as above. The code becomes, still using the javascript magic

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

Then, from a ipython cell,

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

Contrary to the first solution, modifications of notebook's name are updated immediately and there is no need to refresh the notebook.

Horatia answered 12/5, 2014 at 21:54 Comment(11)
Maybe I missed something, but how do you invoke the javascript code from python?Siple
It is also possible to call the javascript from within python using the display method applied to a javascript object like def getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))Chromate
How do I modify this to get the notebook's path?Barrens
@PedroMDuarte: You can use IPython.notebook.notebook_path in javascript for 'thename' in the above script to get that value.Hodosh
@PedroMDuarte: Note that the path is relative to the root of the notebook server.Hodosh
@Jakob: it works fine if done in a cell, but not in a function as you have it. I asked a question about this here.Harbor
@PierreD Well, you cannot immediately return the value but it gets stored as theNotebook. Nevertheless, I also would prefer a solution to directly get such variables.Chromate
The second solution, which looks for the notebook-name <input> element has another advantage: If you rename a notebook, this method immediately reflects this, while the body attribute is only updated when you close and re-open the notebook.Autotype
To get the notebook path without JS trickery: globals()['_dh'][0]Swellhead
I tried but got "ReferenceError: Can't find variable: IPython" on the browser console log. I also tried to "Import IPython" in a code cell before executing this, same issue. Btw: I am trying this on google colab, perhaps this doesn't work there?Gratianna
@BND, just tried it on IPython 7.12.0 and Python 3.7: It works. What versions are you using?Swellhead
P
32

As already mentioned you probably aren't really supposed to be able to do this, but I did find a way. It's a flaming hack though so don't rely on this at all:

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

I updated my answer to include a solution that "works" in IPython 2.0 at least with a simple test. It probably isn't guaranteed to give the correct answer if there are multiple notebooks connected to the same kernel, etc.

Perseverance answered 24/10, 2012 at 18:35 Comment(8)
connection_file_path = kernel.get_connection_file() doesn't work anymore, filename is required arg.Ioannina
This worked fine for me on IPython.__version__ of '0.13.2' and I didnot have to specify a filename for the kernel.get_connection_file()Disobedient
Some updates: Instead of from IPython.lib import kernel now it's just from IPython import kernel. Also instead of using the key 'name' in the dictionaries, use the key 'path'Hodosh
As advertised by the answerer himself, this answer doesn't work for latest IPython. I've created a version that seems to work with IPython 4.2.0 in Python 3.5: gist.github.com/mbdevpl/f97205b73610dd30254652e7817f99cbShouldst
As of version 4.3.0, you need to provide an auth token. This can be retrieved using notebook.notebookapp.list_running_servers().Illaudable
If you have multiple servers running, you can check what port the kernel's parent process is listening on, which should tell you which server to connect to (or you can just connect to every local Jupyter server and check which is running your kernel).Illaudable
if you have multiple servers running, you can list all of them using !jupyter notebook list This will give all running notebooks and then use the one with the correct pwd, or just check them allTali
This may be outdated, another answer in this thread below shows that not only it is fine but fairly easy to get the name of the current notebook from within itself.Scherman
A
31

It seems I cannot comment, so I have to post this as an answer.

The accepted solution by @iguananaut and the update by @mbdevpl appear not to be working with recent versions of the Notebook. I fixed it as shown below. I checked it on Python v3.6.1 + Notebook v5.0.0 and on Python v3.6.5 and Notebook v5.5.0.

import jupyterlab
if jupyterlab.__version__.split(".")[0] == "3":
    from jupyter_server import serverapp as app
    key_srv_directory = 'root_dir'
else : 
    from notebook import notebookapp as app
    key_srv_directory = 'notebook_dir'
import urllib
import json
import os
import ipykernel

def notebook_path(key_srv_directory, ):
    """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 app.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[key_srv_directory],sess['notebook']['path'])
        except:
            pass  # There may be stale entries in the runtime directory 
    return None

As stated in the docstring, this works only when either there is no authentication or the authentication is token-based.

Note that, as also reported by others, the Javascript-based method does not seem to work when executing a "Run all cells" (but works when executing cells "manually"), which was a deal-breaker for me.

Animated answered 5/9, 2018 at 14:16 Comment(4)
Is there any library for this?Sieber
The failure of Javascript methods was a deal-breaker for me too. Thanks for posting this alternative!Hetzel
I have to replace srv['notebook_dir'] with from jupyter_core.paths import jupyter_config_dir; from traitlets.config import Config; 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']Hightest
@Animated making lots of assumptions for when line count is relevant, maybe it can be reduced to this from jupyter_server import serverapp as app; import ipykernel, requests, os; kernel_id = os.path.basename(ipykernel.get_connection_file()).split('-', 1)[1].split('.')[0]; srv = next(app.list_running_servers()); nb_path = srv["root_dir"]+"/"+next(s for s in requests.get(srv['url']+'api/sessions?token='+srv['token']).json() if s["kernel"]["id"]==kernel_id)['notebook']['path']Limiting
A
30

The ipyparams package can do this pretty easily.

import ipyparams
currentNotebook = ipyparams.notebook_name
Appositive answered 19/3, 2020 at 12:10 Comment(5)
Hi @bill, I tried this solution on recent jupyter notebook version but I didn't manage to make it work. I create a post [here]Conics
I found the solution with the package ipynbnameConics
as usual on SO - the marked answer is prob most unhelpful and the best answer is buried on the bottomBellinzona
ipynbname is also now on conda. conda install -c conda-forge ipynbnameSzechwan
This is very unreliable. It worked yesterday but not today. There is indeed an open issueZygosis
C
28

On Jupyter 3.0 the following works. Here I'm showing the entire path on the Jupyter server, not just the notebook name:

To store the NOTEBOOK_FULL_PATH on the current notebook front end:

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

To then display it:

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)

Running the first Javascript cell produces no output. Running the second Python cell produces something like:

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb
Condescending answered 19/6, 2015 at 15:55 Comment(7)
This is very clean. How would you call the Javascript code from a Python function then?Mandy
Hmmmm... maybe in that case you should append the port with a colon followed by the port number?Condescending
This is relative path not full pathTattan
This also doesn't include the setting of c.NotebookApp.notebook_dir.Jungly
at least using a recent version of Jupyter, this doesn't capture the full pathSieber
NameError: name 'NOTEBOOK_FULL_PATH' is not defined when trying on colabCe
I am getting Javascript Error: IPython is not defined. How can I load IPython for javascriptHin
R
8

Yet another hacky solution since my notebook server can change. Basically you print a random string, save it and then search for a file containing that string in the working directory. The while is needed because save_checkpoint is asynchronous.

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)
Rafaelita answered 28/7, 2020 at 13:3 Comment(2)
This is great. Other Javascript based solutions haven't been working well in my environment (sagemaker studio). This one does though!Whaler
Why does it require the 'while' loop, why does 'grep' need to be re-run so many times?Battery
A
7

just use ipynbname , which is practical

#! pip install ipynbname

import ipynbname
nb_fname = ipynbname.name()
nb_path = ipynbname.path()
print(f"{nb_fname=}")
print(f"{nb_path=}")

I found this in https://mcmap.net/q/76516/-get-current-jupyter-lab-notebook-name-for-jupyter-lab-version-2-1-and-3-0-1-and-notebook-version-gt-6-0-3

Aslant answered 21/12, 2022 at 8:15 Comment(0)
C
6

There is no real way yet to do this in Jupyterlab. But there is an official way that's now under active discussion/development as of August 2021:

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

In the meantime, hitting the api/sessions REST endpoint of jupyter_server seems like the best bet. Here's a cleaned-up version of that approach:

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']

Tested working with

python==3.9
jupyter_server==1.8.0
jupyterlab==4.0.0a7
Carpeting answered 8/9, 2021 at 3:46 Comment(3)
I always thought of so many applications of knowing the notebook filename (e.g. based on the filename one could import different sets of modules for a given notebook). Truly this functionality is much needed, ideally it should be perhaps built into the jupyter's core package itself.Refrigerate
@Ramirez Literally no one on Stackoverflow cares about your two cents. However, if you post your view/use cases to the "pass notebook name to kernel" feature discussion thread, the actual Jupyter devs will read them and likely respondCarpeting
Thank you! Worked for me, with jupyterlab==3.3.4 and Python 3.7Axolotl
A
5

If you are using Visual Studio Code:

import IPython ; IPython.extract_module_locals()[1]['__vsc_ipynb_file__']
Aluminize answered 4/6, 2022 at 9:40 Comment(1)
just __vsc_ipynb_file__ works as well in vscodeThyrotoxicosis
L
4

Modifying @jfb method, gives the function below which worked fine on ipykernel-5.3.4.

def getNotebookName():
    display(Javascript('IPython.notebook.kernel.execute("NotebookName = " + "\'"+window.document.getElementById("notebook_name").innerHTML+"\'");'))
    try:
        _ = type(NotebookName)
        return NotebookName
    except:
        return None

Note that the display javascript will take some time to reach the browser, and it will take some time to execute the JS and get back to the kernel. I know it may sound stupid, but it's better to run the function in two cells, like this:

nb_name = getNotebookName()

and in the following cell:

for i in range(10):
    nb_name = getNotebookName()
    if nb_name is not None:
        break

However, if you don't need to define a function, the wise method is to run display(Javascript(..)) in one cell, and check the notebook name in another cell. In this way, the browser has enough time to execute the code and return the notebook name.

If you don't mind to use a library, the most robust way is:

import ipynbname
nb_name = ipynbname.name()
Luckey answered 24/11, 2021 at 20:10 Comment(3)
The option with ipynbname is the ONLY ONE straight forward. All the other I have to deal with installation of IPyton, Javablahblah, and so on. ThanksBroadbrim
ipynbname takes 16 seconds to execute in my minimal notebook.Hecate
@Hecate - latest version of ipynbname is faster. You may have many old and stale nbserver files, assuming you are using JupyterLab.Nitrobenzene
A
3

Nowadays this was implemented as a feature in IPython, there is a built-in "vsc_ipynb_file" variable.

This is the fix - https://github.com/microsoft/vscode-jupyter/pull/8531

Afterbirth answered 13/3, 2023 at 11:2 Comment(1)
This comment is misleading, this is only applicable to people using VSCode.Abbotsen
E
2

To realize why you can't get notebook name using these JS-based solutions, run this code and notice the delay it takes for the message box to appear after python has finished execution of the cell / entire notebook:

%%javascript

function sayHello() {
    alert('Hello world!');
}

setTimeout(sayHello, 1000);
  • More info

Javascript calls are async and hence not guaranteed to complete before python starts running another cell containing the code expecting this notebook name variable to be already created... resulting in NameError when trying to access non-existing variables that should contain notebook name.

I suspect some upvotes on this page became locked before voters could discover that all %%javascript-based solutions ultimately don't work... when the producer and consumer notebook cells are executed together (or in a quick succession).

Evidential answered 17/3, 2021 at 11:53 Comment(0)
U
1

Assuming you have the Jupyter Notebook server's host, port, and authentication token, this should work for you. It's based off of this answer.

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()]

Example usage:

get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')
Uremia answered 22/10, 2019 at 17:36 Comment(0)
T
1

All Json based solutions fail if we execute more than one cell at a time because the result will not be ready until after the end of the execution (its not a matter of using sleep or waiting any time, check it yourself but remember to restart kernel and run all every test)

Based on previous solutions, this avoids using the %% magic in case you need to put it in the middle of some other code:

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))

For python 3, the following based on the answer by @Iguananaut and updated for latest python and possibly multiple servers will work:

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}]')
    
Tali answered 24/9, 2020 at 5:25 Comment(0)
F
1

It's possible to get the current notebook name from the global variable __session__. It's also possible to get it from the environment variable JPY_SESSION_NAME.

A small note: This only works when the session is started with Jupyter. And if the notebook is moved and the session is not restarted, the name will remain the old one.

Tested with

python == 3.11.7
ipykernel == 6.29.0
jupyter_server == 2.12.5
jupyterlab == 4.0.11

See also:

Falkner answered 30/1 at 7:28 Comment(0)
S
0

This works for me in JetBrains DataSpell.

print(str(__session__).split('/')[-1])
<<< output: Салют-Хабаровск-2.ipynb
Single answered 15/2 at 16:37 Comment(0)
M
0

A simple way to do this is to get the connection file and then reading the json data, specifically retrieving "jupyter_session"

So here's a code sample:

from ipykernel import get_connection_file
import os
import json

connection_file = get_connection_file()
notebook_path = os.path.dirname(connection_file)

f = open(connection_file)
data = json.load(f)
data["jupyter_session"] # Your information lives here!

Edit:

Apparently, the above wouldn't work for vscode. Besides, the connection file does not update the file name session variable if it has been renamed in that session, so the above is probably not the best way to do it anyway. But could you please try the below?

As discussed here get .ipynb filename

def get_notebook_name(filename_only=True, full_path=False):

import re
import os
import json    
import requests
from requests.compat import urljoin

from jupyter_server import serverapp
from ipykernel import get_connection_file    

result = ''
# print(filename_only)
# print(full_path)

if filename_only and full_path:
    raise ValueError("filename_only & full_path cannot simultaneously be true (use one or the other)")

connection_file = get_connection_file()
mo = re.search('kernel-(.*).json', connection_file) # matched objects (mo)
kernel_id = mo.group(1)

# Specifically for jupyter lab / analogous function exists for jupyter notebook
servers = serverapp.list_running_servers()

for ss in servers:
    response = requests.get(urljoin(ss['url'], 'api/sessions'), params={'token': ss.get('token', '')})
    for nn in json.loads(response.text):
        if nn['kernel']['id'] == kernel_id:
            relative_path = nn['notebook']['path']

filename = relative_path.split('/')[-1]

if filename_only:
    result = filename
    return result

if full_path:
    cwd = os.getcwd()
    result = os.path.join(cwd, filename)
    return result

Usage of the above function would be something like:

get_notebook_name(True, False)

or

get_notebook_name(False, True)

But of course you could play around and make it unique to your requirements ...

Let me know how it goes!

Meerschaum answered 17/2 at 13:14 Comment(2)
Thanks for the suggestion, @lambda-dot-joburg! It doesn't seem to work for me using vscode; maybe it's implementation-dependant?Arrestment
Perhaps I neglected to take into consideration your requirement for vscode. As far as I know, this should work for jupyter lab and jupyter notebook on a browser-based environment. I will however, post an alternate version to achieve this, which works even better.Meerschaum

© 2022 - 2024 — McMap. All rights reserved.