Ipython: Comment déterminer le chemin du fichier ipynb actuel à partir d'IPython ?

Créé le 5 janv. 2017  ·  15Commentaires  ·  Source: ipython/ipython

Existe-t-il un moyen de déterminer le fichier ipynb actuel à partir d'iPython ?

Cas d'utilisation : je souhaite déclencher des simulations depuis IPython. Pour que tout soit documenté, je souhaite copier le bloc-notes IPython dans le dossier des résultats, idéalement depuis IPython.

La recherche sur le Web avec ce problème a montré qu'il semble y avoir beaucoup d'intérêt pour une telle fonctionnalité, mais les solutions présentées sur stackoverflow semblaient toutes un peu hacky. Ou est-ce déjà implémenté ?

Commentaire le plus utile

Excusez-moi, mais avec ceci :

!echo %cd% # under windows
!pwd # under linux/mac

vous obtenez les informations souhaitées.
Pour le réutiliser, il suffit de faire :

myInfo01 = !echo %cd% # under windows
myInfo02 = !pwd # under linux/mac

Tous les 15 commentaires

Ce n'est pas possible, pas sans hack qui ne fonctionnera pas (affichage de Javascript qui exécute du code Python).

Voici quelques raisons pour lesquelles le noyau (dans ce cas IPython):

  • peut ne pas fonctionner à partir d'un seul fichier
  • même s'il s'agit d'un fichier, le fichier peut ne pas être un bloc-notes.
  • même s'il s'agit d'un bloc-notes, le bloc-notes peut ne pas se trouver sur un système de fichiers.
  • même s'il s'agit d'un système de fichiers, il se peut qu'il ne se trouve pas sur la même machine.
  • même si sur la même machine le chemin d'accès au fichier peut ne pas avoir de sens dans le contexte IPython.
  • même si cela a du sens, le protocole Jupyter n'a pas été conçu pour le faire. Et nous n'avons pas l'intention de changer cette abstraction à court ou à long terme.

Cependant, vous _pouvez_ exécuter un bloc-notes sans serveur de bloc-notes via un script externe et copier le bloc-notes en même temps. C'est une manière simple de jupyter nbconvert --execute --output-dir='results/'

J'espère que cela pourra aider.

Peut-être que le fait que vous ayez fermé ce problème indique immédiatement que ce sujet a été discuté en profondeur ailleurs. Pourriez-vous me donner un lien vers la discussion, afin que je puisse mieux comprendre cette décision ?

Sinon, je me demande: pourquoi l'environnement iPython ne peut-il pas définir une variable python, par exemple dans le module IPython dès le démarrage d'un noyau? Cette variable pourrait alors contenir des informations sur la façon dont le noyau a démarré, comme l'URL du bloc-notes iPython.

Il n'y a pas d'endroit particulier où cela est discuté en profondeur, c'est dans de nombreux endroits, mais je vais réutiliser une autre métaphore que j'ai déjà vue.

Vous êtes un auteur de livres. Votre lecteur veut une chose régulièrement. Comme ils s'identifient aux personnages, ils veulent que le personnage principal ait la même couleur d'yeux qu'eux. Comment tu fais ça ? Eh bien, en tant qu'auteur de livres, vous ne pouvez pas. Pour chaque personne, la réponse est évidente, mais pour la majorité des utilisateurs, vous ne pouvez pas.

Vous pouvez imprimer 10 versions avec 10 couleurs d'yeux et demander au lecteur de choisir. Mais le lecteur doit le faire.

Il en va de même pour le noyau IPython.

Le noyau ne sait pas ce qui l'a déclenché. Les choses qui ont commencé pourraient _essayer_ de définir une variable env, mais cela pourrait même ne pas avoir de sens dans ce contexte. Vous n'avez peut-être pas d'ordinateur portable connecté. Le processus que vous démarrez n'est peut-être pas python.

Vous avez une chose (votre noyau) dont le seul but est d'exécuter du code. Il peut ou non avoir accès à un système de fichiers, il peut ou non être en python. Il peut ou non être même déjà connecté à une interface. il peut ou non être connecté à plusieurs clients au cours de sa vie, voire simultanément.

Ainsi, alors que dans chaque cas, vous _pouvez probablement_ donner une réponse définitive quant à savoir s'il existe un document attaché à un noyau et ce qu'il est, la réponse générale et comment l'obtenir n'est pas claire. La question n'a pas de sens, ou du moins nous n'en avons pas trouvé.

Donc, en tant que lecteur de livres, vous devez faire un choix et dire au noyau le nom de fichier qui _vous_ pensez être le bon.

Lorsque le serveur de bloc-notes démarre, définissez le nom du fichier qui lui est lié. Il y a des défis techniques pour le faire, principalement pas de composants de couplage, mais supposons que nous le pouvons. Quelques questions du haut de ma tête.

Lorsque vous exécutez votre ordinateur portable via nbconvert, quel nom définissez-vous ?

  • si l'entrée est stdin ?
  • si l'entrée est réseau
  • si cahier de sortie =! input_notebook
  • en mode "bookbook" qui prend plusieurs cahiers en entrée.
    Lorsque vous attachez une console, quel nom définissez-vous ?
    Si vous attachez plusieurs cahiers, quel nom définissez-vous ?

    • Si vous exécutez plusieurs cahiers à la suite, quel nom définissez-vous ?

    • Si vous exécutez plusieurs cahiers en parallèle, quel nom définissez-vous ?

      quand on travaille dans un env sans filesystem (postgres DB), quel nom ?

      Binaire ou ASCII ? Encodage défini ?

      Nom de bloc-notes de FullPath ?

      Et si ce n'est pas sur la même machine ?

      Que se passe-t-il si l'exécution est purement en mémoire parce que le bloc-notes a été généré à la volée ?

      Même si vous avez un nom et print() ... et si le fichier est renommé ?

  • renommé alors que le noyau est éteint ?
  • renommé lors de l'exécution du noyau ?
    Collaboration en temps réel et liens durs lorsqu'un fichier peut avoir plusieurs noms, lequel est le bon ?

Aucune des questions ci-dessus n'a de réponse claire pour moi. S'il y a un consensus sur la façon de le faire correctement, sans nous bloquer dans un coin on y réfléchira, et puis il y aura toutes les difficultés techniques.

J'espère que cela clarifie un peu les choses. Vous pouvez essayer des trucs hackish comme celui -ci, mais vous verrez qu'ils contentent rarement tout le monde.

Excusez-moi, mais avec ceci :

!echo %cd% # under windows
!pwd # under linux/mac

vous obtenez les informations souhaitées.
Pour le réutiliser, il suffit de faire :

myInfo01 = !echo %cd% # under windows
myInfo02 = !pwd # under linux/mac

Cela ne fonctionnera pas car le processus CWD peut changer et peut même ne pas être là où le bloc-notes est stocké.

Est-il au moins garanti que si vous ouvrez un bloc-notes dans un nouveau serveur de bloc-notes et démarrez implicitement un noyau en exécutant du code, il obtiendra pwd le dossier dans lequel se trouve le fichier ipynb?

Ce n'est pas parce qu'ipython ne peut pas gérer comme par magie tous les cas étranges, ce à quoi personne ne s'attendait, ne devrait pas l'empêcher d'avoir une règle _simple_ comme celle-ci pour les cas _simples_ dont les gens se soucient réellement (comme remettre un cahier + des fichiers de données dans le même dossier aux étudiants)

Est-il au moins garanti que si vous ouvrez un bloc-notes dans un nouveau serveur de bloc-notes et démarrez implicitement un noyau en exécutant du code, il obtiendra pwd le dossier dans lequel se trouve le fichier ipynb?

Non.

Il n'est pas garanti que le noyau soit sur la même machine que l'ipynb, il n'est même pas garanti que le fichier ipynb existe même, existera, est unique, ou a un chemin unique, ou même est/sera un fichier. Exemple : collaboration en temps réel sur google drive.

Je pense que je n'ai pas assez bien formulé ma question. 200 étudiants auront une configuration d'environnement python, la plupart en installant anaconda sur leurs propres ordinateurs portables. Je leur remettrai l'exercice informatique sous forme de cahier et les fichiers de données dans un dossier. L'un d'eux peut stocker le bloc-notes dans la base de données postgres, deux peuvent exécuter le noyau sur une machine différente de celle de leur ordinateur portable sur lequel ils ont le bloc-notes. Trois étudiants configureront ensemble une collaboration en temps réel sur Google Drive. Six étudiants feront autre chose que vous n'avez peut-être pas mentionné jusqu'à présent. Je pense principalement aux 190 étudiants qui vont raisonnablement suivre les instructions, décompresser le dossier sur leur propre portable (Windows, OS X ou Linux), démarrer un serveur portable sur le _même_ portable (soit par l'explorateur de serveur portable, soit double-cliquant sur le fichier notebook), et laissez-le démarrer implicitement un nouveau noyau (à nouveau sur le même ordinateur portable) en exécutant la première cellule. La question est de savoir si cwd fonctionne pour _ces_ étudiants. Est-ce qu'environ 15 étudiants viendront à mon bureau parce que os.getcwd() n'a pas fonctionné ou dois-je m'attendre à plus de 50-100 ?

Je pense principalement aux 190 étudiants qui vont raisonnablement suivre les instructions, décompresser le dossier sur leur propre ordinateur portable (Windows, OS X ou Linux), démarrer un serveur portable sur le même ordinateur portable (soit par l'explorateur de serveur portable, soit double-cliquant sur le fichier notebook), et laissez-le démarrer implicitement un nouveau noyau (à nouveau sur le même ordinateur portable) en exécutant la première cellule.

Oui, utiliser os.cwd() ou même c = !cwd fonctionnera pour ces utilisateurs ; et je pense que dans votre contexte, c'est bien de leur demander de le faire. Mais en tant que cas d'utilisation _général_, ce n'est pas le cas. nous essaierons également d'être prudents lorsque nous énonçons des choses sur ce bug tracker car cela peut passer pour une approbation explicite de cette méthode. Et nous savons que les gens ne lisent pas en profondeur.

Assez juste, merci pour votre souci de communication précise.

La première fois que le script est exécuté dans un classeur, et avant de le modifier, os.cwd() est le répertoire du bloc-notes.
Donc, ce que j'utilise souvent dans mon code est

if not 'workbookDir' in globals():
    workbookDir = os.getcwd()
print('workbookDir: ' + workbookDir)
os.chdir(workbookDir)  # If you changed the current working dir, this will take you back to the workbook dir.

Comme il semble, la plupart des utilisateurs ici ne veulent pas vraiment accéder au "chemin du bloc-notes", quoi que cela puisse signifier dans un déploiement donné, mais plutôt accéder aux ressources associées à ce bloc-notes, de telle sorte que le les détails du déploiement sont résumés.

De toute évidence, la distribution de blocs-notes avec les données associées est un cas d'utilisation général et large. Peut-être faut-il un mécanisme abstrait pour accéder aux ressources à partir d'un noyau ? Il serait alors de la responsabilité du déploiement (c'est-à-dire l'installation du serveur de bloc-notes) de configurer correctement cette API d'accès aux ressources, éventuellement à l'aide de certaines métadonnées du bloc-notes ? Ensuite, le serveur de bloc-notes local pourrait par défaut servir ces ressources à partir d'un chemin relatif au bloc-notes. D'autres déploiements peuvent fournir une interface distincte (telle qu'une méthode de téléchargement ou une URL pointant vers des ressources) ou simplement ne pas prendre en charge l'interface du tout.

Il est peut-être trop tard maintenant, mais il semble que Colaboratory pourrait vous aider dans votre travail :
https://colab.research.google.com/notebooks/welcome.ipynb

Une variable nommée "_dh" est insérée dans les variables globales au démarrage du notebook. Il semble que ce soit le répertoire du notebook, bien que je n'aie recherché aucune documentation à ce sujet. Cela fonctionne pour moi en ce moment, cependant.

Semblable à la solution de @SurealCereal de :

if not 'workbookDir' in globals():
    workbookDir = os.getcwd()

J'utilise ceci juste après mes importations:

try: ipynb_path
except NameError: ipynb_path = os.getcwd()

Quelque chose dans le mot « erreur » me fait réfléchir à deux fois avant de jouer avec sa position ou son existence.

Alternativement :

if 'workbookDir' not in globals():

est peu plus lisible.

Cette page vous a été utile?
0 / 5 - 0 notes