Я намагаюся отримати поточне ім'я 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)
Вихід []: 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, схоже, не працюють з останніми версіями блокнота. Я виправив це, як показано нижче. Я перевірив це на 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}]')