Próbuję uzyskać aktualną nazwę NoteBook podczas uruchamiania notebooka IPython. Wiem, że widzę to na górze notesu. Po co mi coś takiego
currentNotebook = IPython.foo.bar.notebookname()
Muszę uzyskać nazwę w zmiennej.
python
jupyter-notebook
ipython
jupyter
jupyter-lab
Tooblippe
źródło
źródło
pip install ipynbname
Odpowiedzi:
Jak już wspomniano, prawdopodobnie nie powinieneś być w stanie tego zrobić, ale znalazłem sposób. To jednak płonący hack, więc nie polegaj wcale na tym:
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
Zaktualizowałem swoją odpowiedź, aby zawierała rozwiązanie, które „działa” w IPython 2.0, przynajmniej za pomocą prostego testu. Prawdopodobnie nie ma gwarancji udzielenia poprawnej odpowiedzi, jeśli do tego samego jądra jest podłączonych wiele notebooków itp.
źródło
from IPython.lib import kernel
teraz to po prostufrom IPython import kernel
. Zamiast używać klucza „nazwa” w słownikach, użyj klucza „ścieżka”notebook.notebookapp.list_running_servers()
.Mam następujące, które działają z IPython 2.0. Zauważyłem, że nazwa notatnika jest przechowywana jako wartość atrybutu
'data-notebook-name'
w<body>
tagu strony. Dlatego pomysł polega na tym, aby najpierw poprosić Javascript o pobranie atrybutu - dzięki%%javascript
magii można wywoływać javascripts z komórki kodowej . Następnie możliwy jest dostęp do zmiennej Javascript poprzez wywołanie jądra Pythona za pomocą polecenia ustawiającego zmienną Pythona. Ponieważ ta ostatnia zmienna jest znana z jądra, można uzyskać do niej dostęp również w innych komórkach.%%javascript var kernel = IPython.notebook.kernel; var body = document.body, attribs = body.attributes; var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'"; kernel.execute(command);
Z komórki kodu Python
Out []: HowToGetTheNameOfTheNoteBook.ipynb
Wadą tego rozwiązania jest to, że po zmianie tytułu (nazwy) notatnika nazwa ta wydaje się nie być aktualizowana od razu (prawdopodobnie jest jakaś pamięć podręczna) i konieczne jest ponowne załadowanie notatnika, aby uzyskać dostęp do nowe imie.
[Edytuj] Po namyśle, bardziej efektywnym rozwiązaniem jest wyszukanie pola wprowadzania nazwy notatnika zamiast
<body>
tagu. Patrząc na źródło, okazuje się, że to pole ma identyfikator „nazwa_ notebooka”. Następnie można złapać tę wartość przez a,document.getElementById()
a następnie zastosować to samo podejście, co powyżej. Kod nadal używa magii javascript%%javascript var kernel = IPython.notebook.kernel; var thename = window.document.getElementById("notebook_name").innerHTML; var command = "theNotebook = " + "'"+thename+"'"; kernel.execute(command);
Następnie z komórki Ipython
In [11]: print(theNotebook) Out [11]: HowToGetTheNameOfTheNoteBookSolBis
W przeciwieństwie do pierwszego rozwiązania, modyfikacje nazwy notebooka są aktualizowane natychmiast i nie ma potrzeby odświeżania notebooka.
źródło
def getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
globals()['_dh'][0]
dodawanie do poprzednich odpowiedzi,
aby uzyskać nazwę notatnika, uruchom w komórce następujące polecenie:
%%javascript IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')
w ten sposób otrzymasz nazwę pliku w nb_name
następnie, aby uzyskać pełną ścieżkę, możesz użyć następującego w osobnej komórce:
import os nb_full_path = os.path.join(os.getcwd(), nb_name)
źródło
IPython.notebook.notebook_name
można to zrobić za pomocą%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
Javascript Error: IPython is not defined
Na Jupyter 3.0 działa następująco. Tutaj pokazuję całą ścieżkę na serwerze Jupyter, a nie tylko nazwę notatnika:
Aby zapisać w
NOTEBOOK_FULL_PATH
bieżącym interfejsie notebooka:%%javascript var nb = IPython.notebook; var kernel = IPython.notebook.kernel; var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'"; kernel.execute(command);
Aby go następnie wyświetlić:
print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)
Uruchomienie pierwszej komórki JavaScript nie daje żadnych wyników. Uruchomienie drugiej komórki Pythona daje coś takiego:
źródło
c.NotebookApp.notebook_dir
.Javascript Error: IPython is not defined
. Jak mogę załadować IPython dla javascriptWygląda na to, że nie mogę komentować, więc muszę to opublikować jako odpowiedź.
Rozwiązanie zaakceptowane przez @iguananaut i aktualizacja @mbdevpl wydają się nie działać z najnowszymi wersjami notebooka. Naprawiłem to, jak pokazano poniżej. Sprawdziłem to na Pythonie 3.6.1 + Notebook v5.0.0 oraz na Pythonie v3.6.5 i 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
Jak stwierdzono w dokumentacji, działa to tylko wtedy, gdy nie ma uwierzytelnienia lub uwierzytelnianie jest oparte na tokenach.
Zwróć uwagę, że, jak donoszą również inni, metoda oparta na Javascript nie wydaje się działać podczas wykonywania polecenia „Uruchom wszystkie komórki” (ale działa podczas wykonywania komórek „ręcznie”), co było dla mnie przełomem.
źródło
Ipyparams Pakiet może to zrobić bardzo łatwo.
import ipyparams currentNotebook = ipyparams.notebook_name
źródło
Zakładając, że masz hosta, port i token uwierzytelniający serwera Jupyter Notebook, powinno to działać. Opiera się na tej odpowiedzi .
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()]
Przykładowe użycie:
get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')
źródło
Kolejne hakerskie rozwiązanie, ponieważ mój serwer notebooka może się zmienić. Zasadniczo drukujesz losowy ciąg, zapisujesz go, a następnie szukasz pliku zawierającego ten ciąg w katalogu roboczym. Czas jest potrzebny, ponieważ funkcja save_checkpoint jest asynchroniczna.
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)
źródło
Wszystkie rozwiązania oparte na Json zawodzą, jeśli wykonujemy więcej niż jedną komórkę naraz, ponieważ wynik będzie gotowy dopiero po zakończeniu wykonywania (nie jest to kwestia użycia uśpienia lub czekania w dowolnym momencie, sprawdź to sam, ale pamiętaj o ponownym uruchomieniu jądra) i uruchom wszystkie testy)
Opierając się na poprzednich rozwiązaniach, pozwala to uniknąć używania magii %% na wypadek, gdybyś musiał umieścić ją w środku innego kodu:
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))
W przypadku Pythona 3, następujące, oparte na odpowiedzi @Iguananaut i zaktualizowane pod kątem najnowszego Pythona i prawdopodobnie wielu serwerów, będą działać:
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}]')
źródło