Estou tentando obter o nome do Bloco de notas atual ao executar o bloco de notas IPython. Eu sei que posso ver na parte superior do caderno. O que eu estou atrás de algo como
currentNotebook = IPython.foo.bar.notebookname()
Preciso colocar o nome em uma variável.
python
jupyter-notebook
ipython
jupyter
jupyter-lab
Tooblippe
fonte
fonte
pip install ipynbname
Respostas:
Como já mencionei, provavelmente você não deveria ser capaz de fazer isso, mas encontrei uma maneira. É um hack inflamado, então não confie nisso:
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
Atualizei minha resposta para incluir uma solução que "funciona" no IPython 2.0 pelo menos com um teste simples. Provavelmente não é garantido que a resposta correta seja dada se houver vários notebooks conectados ao mesmo kernel, etc.
fonte
from IPython.lib import kernel
agora é sófrom IPython import kernel
. Além disso, em vez de usar a chave 'nome' nos dicionários, use a chave 'caminho'notebook.notebookapp.list_running_servers()
.Eu tenho o seguinte que funciona com IPython 2.0. Observei que o nome do notebook fica armazenado como o valor do atributo
'data-notebook-name'
na<body>
tag da página. Portanto, a ideia é primeiro pedir ao Javascript para recuperar o atributo - os javascripts podem ser invocados a partir de um codecell graças à%%javascript
magia. Então é possível acessar a variável Javascript através de uma chamada ao Kernel Python, com um comando que define uma variável Python. Como esta última variável é conhecida no kernel, ela pode ser acessada em outras células também.%%javascript var kernel = IPython.notebook.kernel; var body = document.body, attribs = body.attributes; var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'"; kernel.execute(command);
De uma célula de código Python
Out []: HowToGetTheNameOfTheNoteBook.ipynb
Um defeito desta solução é que quando alguém muda o título (nome) de um notebook, então este nome parece não ser atualizado imediatamente (provavelmente existe algum tipo de cache) e é necessário recarregar o notebook para ter acesso ao novo nome.
[Editar] Pensando bem, uma solução mais eficiente é procurar o campo de entrada para o nome do caderno em vez da
<body>
tag. Olhando para a fonte, parece que este campo tem id "notebook_name". Então, é possível capturar esse valor por adocument.getElementById()
e seguir a mesma abordagem acima. O código se torna, ainda usando a magia do javascript%%javascript var kernel = IPython.notebook.kernel; var thename = window.document.getElementById("notebook_name").innerHTML; var command = "theNotebook = " + "'"+thename+"'"; kernel.execute(command);
Então, a partir de uma célula ipython,
In [11]: print(theNotebook) Out [11]: HowToGetTheNameOfTheNoteBookSolBis
Ao contrário da primeira solução, as modificações do nome do notebook são atualizadas imediatamente e não há necessidade de atualizar o notebook.
fonte
def getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
globals()['_dh'][0]
adicionando às respostas anteriores,
para obter o nome do notebook, execute o seguinte em uma célula:
%%javascript IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')
isso dá a você o nome do arquivo em nb_name
então, para obter o caminho completo, você pode usar o seguinte em uma célula separada:
import os nb_full_path = os.path.join(os.getcwd(), nb_name)
fonte
IPython.notebook.notebook_name
isso pode ser feito usando%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
Javascript Error: IPython is not defined
No Jupyter 3.0 funciona o seguinte. Aqui, estou mostrando todo o caminho no servidor Jupyter, não apenas o nome do notebook:
Para armazenar
NOTEBOOK_FULL_PATH
no front-end do notebook atual:%%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 então exibi-lo:
print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)
A execução da primeira célula Javascript não produz saída. Executar a segunda célula Python produz algo como:
fonte
c.NotebookApp.notebook_dir
.Javascript Error: IPython is not defined
. Como posso carregar IPython para javascriptParece que não posso comentar, então tenho que postar isso como uma resposta.
A solução aceita por @iguananaut e a atualização por @mbdevpl parecem não estar funcionando com as versões recentes do Notebook. Eu consertei como mostrado abaixo. Eu verifiquei no Python v3.6.1 + Notebook v5.0.0 e no Python v3.6.5 e 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
Conforme declarado na docstring, isso funciona apenas quando não há autenticação ou a autenticação é baseada em token.
Observe que, como também relatado por outros, o método baseado em Javascript não parece funcionar ao executar um "Executar todas as células" (mas funciona ao executar células "manualmente"), o que foi um obstáculo para mim.
fonte
O pacote ipyparams pode fazer isso facilmente.
import ipyparams currentNotebook = ipyparams.notebook_name
fonte
Supondo que você tenha o host, a porta e o token de autenticação do servidor do Notebook Jupyter, isso deve funcionar para você. É baseado nesta resposta .
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()]
Exemplo de uso:
get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')
fonte
Mais uma solução hacky, já que meu servidor de notebook pode mudar. Basicamente, você imprime uma string aleatória, salva-a e, a seguir, procura um arquivo que contém essa string no diretório de trabalho. O while é necessário porque save_checkpoint é assíncrono.
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)
fonte
Todas as soluções baseadas em Json falham se executarmos mais de uma célula ao mesmo tempo porque o resultado não estará pronto até depois do final da execução (não é uma questão de usar o sono ou esperar qualquer momento, verifique você mesmo, mas lembre-se de reiniciar o kernel e execute todos os testes)
Com base em soluções anteriores, isso evita usar a magia %% caso você precise colocá-la no meio de algum outro 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 o python 3, o seguinte com base na resposta de @Iguananaut e atualizado para o python mais recente e possivelmente vários 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}]')
fonte