web-dev-qa-db-fra.com

Comment obtenir le nom actuel du bloc-notes IPython

J'essaie d'obtenir le nom actuel du bloc-notes lors de l'exécution du bloc-notes IPython. Je sais que je peux le voir en haut du cahier. Ce que je recherche après quelque chose

currentNotebook = IPython.foo.bar.notebookname()

J'ai besoin d'obtenir le nom dans une variable.

58
Tooblippe

Comme déjà mentionné, vous n'êtes probablement pas vraiment censé être en mesure de le faire, mais j'ai trouvé un moyen. C'est un hack enflammé, alors ne vous fiez pas du tout à cela:

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

J'ai mis à jour ma réponse pour inclure une solution qui "fonctionne" dans IPython 2.0 au moins avec un simple test. Il n'est probablement pas garanti de donner la bonne réponse s'il y a plusieurs ordinateurs portables connectés au même noyau, etc.

23
Iguananaut

J'ai ce qui suit qui fonctionne avec IPython 2.0. J'ai observé que le nom du bloc-notes est stocké en tant que valeur de l'attribut 'data-notebook-name' Dans la balise <body> De la page. L'idée est donc d'abord de demander à Javascript de récupérer l'attribut - les javascripts peuvent être invoqués à partir d'une cellule codée grâce à la magie %%javascript. Il est ensuite possible d'accéder à la variable Javascript via un appel au noyau Python, avec une commande qui définit une variable Python. Puisque cette dernière variable est connu du noyau, il est également accessible dans d'autres cellules.

%%javascript
var kernel = IPython.notebook.kernel;
var body = document.body,  
    attribs = body.attributes;
var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'";
kernel.execute(command);

À partir d'une cellule de code Python

print(theNotebook)

Out []: HowToGetTheNameOfTheNoteBook.ipynb

Un défaut de cette solution est que lorsque l'on change le titre (nom) d'un bloc-notes, ce nom ne semble pas être mis à jour immédiatement (il y a probablement une sorte de cache) et il est nécessaire de recharger le bloc-notes pour accéder au nouveau nom.

[Modifier] Après réflexion, une solution plus efficace consiste à rechercher le champ de saisie pour le nom du carnet au lieu de la balise <body>. En regardant dans la source, il semble que ce champ ait l'ID "nom_ordinateur portable". Il est alors possible d'attraper cette valeur par une document.getElementById() puis de suivre la même approche que ci-dessus. Le code devient, toujours en utilisant la magie javascript

%%javascript
var kernel = IPython.notebook.kernel;
var thename = window.document.getElementById("notebook_name").innerHTML;
var command = "theNotebook = " + "'"+thename+"'";
kernel.execute(command);

Ensuite, à partir d'une cellule ipython,

In [11]: print(theNotebook)
Out [11]: HowToGetTheNameOfTheNoteBookSolBis

Contrairement à la première solution, les modifications du nom du notebook sont mises à jour immédiatement et il n'est pas nécessaire de rafraîchir le notebook.

34
jfb

ajout aux réponses précédentes,

pour obtenir le nom du bloc-notes, exécutez ce qui suit dans une cellule:

%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

cela vous donne le nom de fichier dans nb_name

puis pour obtenir le chemin complet, vous pouvez utiliser ce qui suit dans une cellule distincte:

import os
nb_full_path = os.path.join(os.getcwd(), nb_name)
28
Mahmoud Elagdar

Sur Jupyter 3.0 les travaux suivants. Ici, je montre le chemin complet sur le serveur Jupyter, pas seulement le nom du bloc-notes:

Pour stocker le NOTEBOOK_FULL_PATH sur le frontal du portable actuel:

%%javascript
var nb = IPython.notebook;
var kernel = IPython.notebook.kernel;
var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'";
kernel.execute(command);

Pour l'afficher ensuite:

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)

L'exécution de la première cellule Javascript ne produit aucune sortie. L'exécution de la deuxième cellule Python produit quelque chose comme:

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb
24

Il semble que je ne puisse pas commenter, donc je dois poster ceci comme réponse.

La solution acceptée par @iguananaut et la mise à jour par @mbdevpl ne semblent pas fonctionner avec les versions récentes du Notebook. Je l'ai corrigé comme indiqué ci-dessous. Je l'ai vérifié sur Python v3.6.1 + Notebook v5.0.0 et sur Python v3.6.5 et 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

Comme indiqué dans la docstring, cela ne fonctionne que lorsqu'il n'y a pas d'authentification ou que l'authentification est basée sur des jetons.

Notez que, comme l'ont également signalé d'autres, la méthode basée sur Javascript ne semble pas fonctionner lors de l'exécution d'un "Exécuter toutes les cellules" (mais fonctionne lors de l'exécution de cellules "manuellement"), ce qui a été pour moi une rupture.

12
P.Toccaceli