Estoy tratando de obtener el nombre actual del Cuaderno de notas cuando ejecuto el cuaderno IPython. Sé que puedo verlo en la parte superior del cuaderno. Lo que estoy buscando algo como
currentNotebook = IPython.foo.bar.notebookname()
Necesito obtener el nombre en una variable.
python
jupyter-notebook
ipython
jupyter
jupyter-lab
Tooblippe
fuente
fuente
pip install ipynbname
Respuestas:
Como ya se mencionó, probablemente no se supone que pueda hacer esto, pero encontré una manera. Sin embargo, es un truco en llamas, así que no confíes en esto en absoluto:
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
Actualicé mi respuesta para incluir una solución que "funciona" en IPython 2.0 al menos con una prueba simple. Probablemente no se garantiza que dé la respuesta correcta si hay varios portátiles conectados al mismo kernel, etc.
fuente
from IPython.lib import kernel
ahora es solofrom IPython import kernel
. Además, en lugar de usar la clave 'nombre' en los diccionarios, use la clave 'ruta'notebook.notebookapp.list_running_servers()
.Tengo lo siguiente que funciona con IPython 2.0. Observé que el nombre del cuaderno se almacena como el valor del atributo
'data-notebook-name'
en la<body>
etiqueta de la página. Por lo tanto, la idea es primero pedirle a Javascript que recupere el atributo: los javascripts se pueden invocar desde una celda de código gracias a la%%javascript
magia. Entonces es posible acceder a la variable de Javascript a través de una llamada al Kernel de Python, con un comando que establece una variable de Python. Dado que esta última variable se conoce del kernel, también se puede acceder a ella en otras celdas.%%javascript var kernel = IPython.notebook.kernel; var body = document.body, attribs = body.attributes; var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'"; kernel.execute(command);
Desde una celda de código Python
Fuera []: HowToGetTheNameOfTheNoteBook.ipynb
Un defecto en esta solución es que cuando se cambia el título (nombre) de un cuaderno, entonces este nombre parece no actualizarse inmediatamente (probablemente hay algún tipo de caché) y es necesario recargar el cuaderno para acceder a la nuevo nombre.
[Editar] Reflexionando, una solución más eficiente es buscar el campo de entrada para el nombre del cuaderno en lugar de la
<body>
etiqueta. Al buscar en la fuente, parece que este campo tiene la identificación "notebook_name". Entonces es posible capturar este valor mediantedocument.getElementById()
ay luego seguir el mismo enfoque que el anterior. El código se convierte, todavía usando la magia de JavaScript%%javascript var kernel = IPython.notebook.kernel; var thename = window.document.getElementById("notebook_name").innerHTML; var command = "theNotebook = " + "'"+thename+"'"; kernel.execute(command);
Luego, desde una celda ipython,
In [11]: print(theNotebook) Out [11]: HowToGetTheNameOfTheNoteBookSolBis
A diferencia de la primera solución, las modificaciones del nombre del portátil se actualizan de inmediato y no es necesario actualizar el portátil.
fuente
def getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
globals()['_dh'][0]
agregando a las respuestas anteriores,
para obtener el nombre del cuaderno, ejecute lo siguiente en una celda:
%%javascript IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')
esto le da el nombre del archivo en nb_name
luego, para obtener la ruta completa, puede usar lo siguiente en una celda separada:
import os nb_full_path = os.path.join(os.getcwd(), nb_name)
fuente
IPython.notebook.notebook_name
esto se puede hacer usando%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
Javascript Error: IPython is not defined
En Jupyter 3.0 funciona lo siguiente. Aquí estoy mostrando la ruta completa en el servidor de Jupyter, no solo el nombre del cuaderno:
Para almacenar
NOTEBOOK_FULL_PATH
en la interfaz actual del portátil:%%javascript var nb = IPython.notebook; var kernel = IPython.notebook.kernel; var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'"; kernel.execute(command);
Para luego mostrarlo:
print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)
La ejecución de la primera celda de Javascript no produce resultados. Ejecutar la segunda celda de Python produce algo como:
fuente
c.NotebookApp.notebook_dir
.Javascript Error: IPython is not defined
. ¿Cómo puedo cargar IPython para javascriptParece que no puedo comentar, así que tengo que publicar esto como respuesta.
La solución aceptada por @iguananaut y la actualización por @mbdevpl parecen no funcionar con versiones recientes del Notebook. Lo arreglé como se muestra a continuación. Lo comprobé en Python v3.6.1 + Notebook v5.0.0 y en Python v3.6.5 y 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
Como se indica en la cadena de documentos, esto solo funciona cuando no hay autenticación o la autenticación está basada en token.
Tenga en cuenta que, como también informaron otros, el método basado en Javascript no parece funcionar cuando se ejecuta "Ejecutar todas las celdas" (pero funciona cuando se ejecutan celdas "manualmente"), lo cual fue un factor decisivo para mí.
fuente
El paquete ipyparams puede hacer esto con bastante facilidad.
import ipyparams currentNotebook = ipyparams.notebook_name
fuente
Suponiendo que tiene el host, el puerto y el token de autenticación del servidor Jupyter Notebook, esto debería funcionar para usted. Se basa en esta respuesta .
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()]
Uso de ejemplo:
get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')
fuente
Otra solución hacky ya que mi servidor portátil puede cambiar. Básicamente, imprime una cadena aleatoria, la guarda y luego busca un archivo que contenga esa cadena en el directorio de trabajo. El while es necesario porque save_checkpoint es asincrónico.
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)
fuente
Todas las soluciones basadas en Json fallan si ejecutamos más de una celda a la vez porque el resultado no estará listo hasta después del final de la ejecución (no se trata de usar la suspensión o esperar en cualquier momento, compruébelo usted mismo, pero recuerde reiniciar el kernel y ejecutar todas las pruebas)
Basado en soluciones anteriores, esto evita usar la magia %% en caso de que necesite ponerlo en medio de algún otro código:
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))
Para python 3, lo siguiente basado en la respuesta de @Iguananaut y actualizado para la última python y posiblemente varios servidores funcionará:
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}]')
fuente