How do I get the current IPython / Jupyter Notebook name
Solution 1
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.
Solution 2
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)
Solution 3
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.
Solution 4
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.
Solution 5
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
Related videos on Youtube
Comments
-
Tooblippe over 2 years
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.
-
Thomas K over 11 yearsWhat 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).
-
Tooblippe over 11 yearsHi, 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.
-
joelostblom over 4 yearsP.Toccaceli's answer works well with recent versions of JupyterLab (1.1.4) (notebook 5.6.0) and does not require javascript.
-
matth about 4 years
-
NeoTT over 3 yearsSome did the work and made a pip package: pypi.org/project/ipynbname install by
pip install ipynbname
-
lhoupert about 3 yearsYes
ipynbname
is now working with jupyter 3 (more details here) -
Admin over 2 years
ipynbname
did not work on jupyter 4 though.
-
-
Purrell over 10 yearsconnection_file_path = kernel.get_connection_file() doesn't work anymore, filename is required arg.
-
Paul over 10 yearsThis 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()
-
Artjom B. almost 10 yearsMaybe I missed something, but how do you invoke the javascript code from python?
-
Jakob almost 10 yearsIt 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+"\'");'))
-
Pedro M Duarte about 9 yearsHow do I modify this to get the notebook's path?
-
Tristan Reid about 9 years@PedroMDuarte: You can use IPython.notebook.notebook_path in javascript for 'thename' in the above script to get that value.
-
Tristan Reid about 9 years@PedroMDuarte: Note that the path is relative to the root of the notebook server.
-
Pierre D almost 9 years@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.
-
Jakob almost 9 years@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.
-
Lukas over 8 yearsThis is very clean. How would you call the Javascript code from a Python function then?
-
Tristan Reid over 8 yearsSome updates: Instead of
from IPython.lib import kernel
now it's justfrom IPython import kernel
. Also instead of using the key 'name' in the dictionaries, use the key 'path' -
mbdevpl almost 8 yearsAs 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/f97205b73610dd30254652e7817f99cb
-
Zephaniah Grunschlag over 7 yearsHmmmm... maybe in that case you should append the port with a colon followed by the port number?
-
Ivelin over 7 yearsThis is relative path not full path
-
yingted over 6 yearsAs of version 4.3.0, you need to provide an auth token. This can be retrieved using
notebook.notebookapp.list_running_servers()
. -
yingted over 6 yearsIf 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).
-
jfb over 6 yearsUsing
IPython.notebook.notebook_name
this can be done using%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
-
sappjw over 6 yearsThis also doesn't include the setting of
c.NotebookApp.notebook_dir
. -
Pierre-Antoine almost 6 yearsFor 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?
-
Mahmoud Elagdar almost 6 yearsI 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".
-
matanster over 5 yearsWhy do we need javascript actually? nothing more native?
-
Mahmoud Elagdar over 5 yearsLet 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 + '\"')")
-
Sunday over 5 yearsThe 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. -
matanster over 5 yearsat least using a recent version of Jupyter, this doesn't capture the full path
-
matanster over 5 yearsIs there any library for this?
-
Fernando Wittmann about 5 yearsNameError: name 'nb_name' is not defined
-
Fernando Wittmann about 5 yearsNameError: name 'NOTEBOOK_FULL_PATH' is not defined when trying on colab
-
Mahmoud Elagdar almost 5 yearsDid the JavaScript part run without errors before you ran the Python part?
-
germ almost 5 yearsTo get the notebook path without JS trickery:
globals()['_dh'][0]
-
alancalvitti almost 5 years@MahmoudElagdar,
"Cell>Run All Bellow"
doesn't seem an option when remotely running the notebook from another notebook with%run
-
alancalvitti almost 5 years@MahmoudElagdar, the d_js method works in a given notebook when called by a wrapper function, say
notebook_name()
that returnsnb_name
. However, it throwsNameError: name 'nb_name' is not defined
when%run
is used to evaluate the notebook containingnotebook_name()
. Any ideas? -
Mahmoud Elagdar over 4 years@alancalvitti 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 runs
-
Arjun A J over 4 years@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. Thanks -
gumption over 4 yearsThe failure of Javascript methods was a deal-breaker for me too. Thanks for posting this alternative!
-
magicrebirth over 4 yearsFails on Jupyter Lab:
Javascript Error: IPython is not defined
-
Dave Babbitt over 4 yearsI 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']
-
zozo about 4 yearsI am getting
Javascript Error: IPython is not defined
. How can I load IPython for javascript -
kawingkelvin about 4 yearsI 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?
-
ntg over 3 yearsif 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 all -
alejandro over 3 yearsThis seems a better answer than the accepted one at the top.
-
alejandro over 3 yearsThis 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.
-
germ over 3 years@BND, just tried it on IPython 7.12.0 and Python 3.7: It works. What versions are you using?
-
lhoupert over 3 yearsHi @bill, I tried this solution on recent jupyter notebook version but I didn't manage to make it work. I create a post [here]
-
lhoupert about 3 yearsI found the solution with the package ipynbname
-
mirekphd about 3 yearsIt'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
. -
Mahmoud Elagdar about 3 years@P.Toccaceli 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']
-
Mahmoud Elagdar about 3 years@mirekphd The async idea is interesting, IDK I tried adding a sleep and still didn't work. Maybe try P.Toccaceli's solution
-
FarisHijazi almost 3 yearsthat's a super weird way but this works great, thank you
-
Warlax56 over 2 yearsThis is great. Other Javascript based solutions haven't been working well in my environment (sagemaker studio). This one does though!
-
Admin over 2 yearsI 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.
-
tel over 2 years@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 respond
-
alEx over 2 yearsThe option with ipynbname is the ONLY ONE straight forward. All the other I have to deal with installation of IPyton, Javablahblah, and so on. Thanks
-
Julian - BrainAnnex.org almost 2 yearsThank you! Worked for me, with jupyterlab==3.3.4 and Python 3.7
-
BSalita almost 2 yearsipynbname takes 16 seconds to execute in my minimal notebook.