Я пытаюсь получить текущее имя NoteBook при запуске ноутбука IPython. Я знаю, что вижу это вверху блокнота. Что мне нужно после чего-то вроде
currentNotebook = IPython.foo.bar.notebookname()
Мне нужно получить имя в переменной.
Я пытаюсь получить текущее имя NoteBook при запуске ноутбука IPython. Я знаю, что вижу это вверху блокнота. Что мне нужно после чего-то вроде
currentNotebook = IPython.foo.bar.notebookname()
Мне нужно получить имя в переменной.
pip install ipynbname
Ответы:
Как уже упоминалось, вы, вероятно, действительно не должны уметь этого делать, но я нашел способ. Это пламенный хакер, так что не стоит на него полагаться:
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
Я обновил свой ответ, включив в него решение, которое «работает» в IPython 2.0, по крайней мере, с помощью простого теста. Вероятно, нет гарантии, что вы получите правильный ответ, если к одному ядру подключено несколько ноутбуков и т. Д.
from IPython.lib import kernel
этого просто from IPython import kernel
. Также вместо использования ключа «имя» в словарях используйте ключ «путь»
notebook.notebookapp.list_running_servers()
.
У меня есть следующее, которое работает с IPython 2.0. Я заметил, что имя записной книжки хранится как значение атрибута 'data-notebook-name'
в <body>
теге страницы. Таким образом, идея состоит в том, чтобы сначала попросить Javascript получить атрибут - javascripts может быть вызван из кодовой ячейки благодаря %%javascript
магии. Затем можно получить доступ к переменной Javascript через вызов ядра Python с помощью команды, которая устанавливает переменную 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);
Из ячейки кода Python
print(theNotebook)
Out []: HowToGetTheNameOfTheNoteBook.ipynb
Недостаток этого решения заключается в том, что при изменении заголовка (имени) записной книжки это имя, кажется, не обновляется сразу (вероятно, есть какой-то кеш), и необходимо перезагрузить записную книжку, чтобы получить доступ к новое имя.
[Править] Поразмыслив, более эффективным решением будет поиск в поле ввода имени записной книжки вместо <body>
тега. Заглянув в источник, выясняется, что это поле имеет идентификатор «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
В отличие от первого решения, модификации имени записной книжки обновляются сразу, и нет необходимости обновлять записную книжку.
def getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
globals()['_dh'][0]
добавление к предыдущим ответам,
чтобы получить имя записной книжки, выполните в ячейке следующее:
%%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)
IPython.notebook.notebook_name
это можно сделать с помощью%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
Javascript Error: IPython is not defined
На 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 не дает никаких результатов. Запуск второй ячейки Python дает что-то вроде:
NOTEBOOK_FULL_PATH:
/user/zeph/GetNotebookName.ipynb
c.NotebookApp.notebook_dir
.
Javascript Error: IPython is not defined
. Как загрузить IPython для javascript
Кажется, я не могу комментировать, поэтому я должен опубликовать это в качестве ответа.
Принятое решение от @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
Как указано в строке документации, это работает только в том случае, если аутентификация отсутствует или аутентификация основана на токенах.
Обратите внимание, что, как также сообщалось другими, метод на основе Javascript, похоже, не работает при выполнении «Запустить все ячейки» (но работает при выполнении ячеек «вручную»), что было для меня нарушителем.
Предполагая, что у вас есть хост, порт и токен аутентификации сервера 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')
Еще одно хакерское решение, поскольку мой ноутбук-сервер может измениться. Обычно вы печатаете случайную строку, сохраняете ее, а затем ищите файл, содержащий эту строку, в рабочем каталоге. Время необходимо, потому что 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)
Все решения на основе 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}]')