Ipython: Wie finde ich den Pfad der aktuellen ipynb-Datei in IPython heraus?

Erstellt am 5. Jan. 2017  ·  15Kommentare  ·  Quelle: ipython/ipython

Gibt es eine Möglichkeit, die aktuelle ipynb-Datei in iPython herauszufinden?

Anwendungsfall: Ich möchte Simulationen aus IPython heraus auslösen. Um alles dokumentiert zu halten, möchte ich das IPython-Notizbuch in den Ergebnisordner kopieren, idealerweise aus IPython heraus.

Die Suche im Internet mit diesem Problem zeigte, dass es ein großes Interesse an einem solchen Feature zu geben scheint, aber die auf Stackoverflow präsentierten Lösungen schienen alle etwas hackig zu sein. Oder ist das bereits implementiert?

Hilfreichster Kommentar

Entschuldigung, aber damit:

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

Sie erhalten die gewünschten Informationen.
Um es wiederzuverwenden, tun Sie einfach:

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

Alle 15 Kommentare

Es ist nicht möglich, nicht ohne Hack, der nicht funktioniert (Anzeigen von Javascript, das Python-Code ausführt).

Hier sind einige Gründe, warum der Kernel (in diesem Fall IPython):

  • kann nicht von einer einzelnen Datei ausgeführt werden
  • Selbst wenn es sich um eine Datei handelt, handelt es sich möglicherweise nicht um ein Notizbuch.
  • Selbst wenn es sich um ein Notebook handelt, befindet sich das Notebook möglicherweise nicht in einem Dateisystem.
  • selbst wenn es sich um ein Dateisystem handelt, befindet es sich möglicherweise nicht auf derselben Maschine.
  • selbst wenn auf demselben Computer der Pfad zur Datei im IPython-Kontext möglicherweise keinen Sinn macht.
  • Auch wenn es Sinn macht, wurde das Jupyter-Protokoll nicht dafür entwickelt. Und wir haben nicht vor, diese Abstraktion kurz- oder langfristig zu ändern.

Allerdings _können_ Sie ein Notebook ohne Notebook-Server über ein externes Skript ausführen und gleichzeitig das Notebook kopieren. Das ist eine einfache Art von jupyter nbconvert --execute --output-dir='results/'

Hoffentlich hilft das.

Vielleicht weist die Tatsache, dass Sie dieses Thema geschlossen haben, sofort darauf hin, dass dieses Thema an anderer Stelle ausführlich diskutiert wurde. Könnten Sie mir einen Link zu der Diskussion geben, damit ich diese Entscheidung besser nachvollziehen kann?

Ansonsten frage ich mich: Warum kann die iPython-Umgebung keine Python-Variable zB innerhalb des IPython-Moduls setzen, sobald ein Kernel gestartet wird? Diese Variable könnte dann Informationen darüber enthalten, wie der Kernel gestartet wurde, wie die URL des iPython-Notebooks.

Es gibt keinen bestimmten Ort, an dem dies ausführlich diskutiert wird, es ist an vielen Stellen, aber ich werde eine andere Metapher wiederverwenden, die ich zuvor gesehen habe.

Sie sind Buchautorin. Ihre Leser wollen regelmäßig etwas. Wenn sie sich mit den Charakteren identifizieren, möchten sie, dass der Hauptcharakter die gleiche Augenfarbe hat wie sie. Wie machst du das ? Nun, als Buchautor kann man das nicht. Für jede einzelne Person ist die Antwort offensichtlich, aber für die Mehrheit der Benutzer ist dies nicht der Fall.

Sie können 10 Versionen mit 10 Augenfarben drucken und den Leser bitten, eine Auswahl zu treffen. Aber der Leser _muss_ es tun.

Dasselbe gilt für den IPython-Kernel.

Der Kernel weiß nicht, was ihn gestartet hat. Die Dinge, die gestartet wurden, könnten _versuchen_, eine env-Variable zu setzen, aber es könnte in diesem Zusammenhang nicht einmal sinnvoll sein. Möglicherweise ist kein Notebook angeschlossen. Der Prozess, den Sie starten, ist möglicherweise nicht Python.

Sie haben ein Ding (Ihren Kernel), dessen einziger Zweck darin besteht, Code auszuführen. Es kann Zugriff auf ein Dateisystem haben oder nicht, es kann Python sein oder nicht. Es kann sogar bereits mit einem Frontend verbunden sein oder auch nicht. Es kann während seiner Lebensdauer mit mehreren Clients verbunden sein oder nicht, vielleicht sogar gleichzeitig.

Während Sie also in jedem Fall _wahrscheinlich_ eine endgültige Antwort darauf geben können, ob ein Dokument an einen Kernel angehängt ist und was es ist, ist die allgemeine Antwort und wie man es bekommt, unklar. Die Frage ergibt keinen Sinn, oder zumindest haben wir keinen gefunden.

Als Buchleser müssen Sie also eine Wahl treffen und dem Kernel den Dateinamen mitteilen, den _Sie_ für den richtigen halten.

Wenn der Notebook-Server startet, legt er den Namen der damit verknüpften Datei fest. Es gibt technische Herausforderungen, hauptsächlich keine Komponenten zu koppeln, aber wir gehen davon aus, dass wir es können. Ein paar Fragen aus dem Kopf.

Welchen Namen legen Sie fest, wenn Sie Ihr Notebook über nbconvert ausführen?

  • wenn die Eingabe stdin ist?
  • wenn die Eingabe ein Netzwerk ist
  • wenn Ausgabe Notizbuch =! input_notebook
  • im "Buchbuch"-Modus, der mehrere Notizbücher in die Eingabe nimmt.
    Welchen Namen legen Sie beim Anschließen einer Konsole fest?
    Wenn Sie mehrere Notizbücher anhängen, welchen Namen legen Sie fest?

    • Wenn Sie mehrere Notebooks hintereinander ausführen, welchen Namen legen Sie fest?

    • Wenn Sie mehrere Notebooks parallel ausführen, welchen Namen legen Sie fest?

      Wenn Sie in einer Umgebung ohne Dateisystem (Postgres-DB) arbeiten, welcher Name?

      Binär oder ASCII? Definierte Codierung ?

      Notebook-Name von FullPath ?

      Was ist, wenn nicht auf der gleichen Maschine?

      Was ist, wenn die Ausführung rein im Arbeitsspeicher erfolgt, weil das Notebook spontan generiert wurde?

      Selbst wenn Sie einen Namen haben und ihn print() ... was ist, wenn die Datei umbenannt wird?

  • umbenannt, während der Kernel ausgeschaltet ist?
  • während Kernel-Ausführung umbenannt?
    Zusammenarbeit in Echtzeit und Hardlinks, wenn eine Datei mehrere Namen haben kann, welcher ist richtig?

Keine der obigen Fragen hat klare Antworten für mich. Wenn es einen Konsens darüber gibt, wie man es richtig macht, ohne uns in einer Ecke zu blockieren, werden wir darüber nachdenken, und dann gibt es all die technischen Schwierigkeiten.

Ich hoffe, das hat die Dinge ein wenig klarer gemacht. Sie können solche hackigen Dinge ausprobieren, aber Sie werden sehen, dass sie selten alle zufrieden stellen.

Entschuldigung, aber damit:

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

Sie erhalten die gewünschten Informationen.
Um es wiederzuverwenden, tun Sie einfach:

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

Es wird nicht funktionieren, da sich der Prozess CWD ändern kann und möglicherweise sogar nicht dort ist, wo das Notizbuch gespeichert ist.

Ist es zumindest garantiert, dass, wenn Sie ein Notebook in einem neuen Notebook-Server öffnen und implizit einen Kernel starten, indem Sie einen Code ausführen, dieser pwd den Ordner erhält, in dem sich die ipynb-Datei befindet?

Nur weil Ipython nicht jeden seltsamen Grenzfall magisch handhaben kann, was meiner Meinung nach niemand erwartet hat, sollte es nicht davon abhalten, eine solche _einfache_ Regel für die _einfachen_ Fälle zu haben, die den Leuten wirklich wichtig sind (wie das Übergeben eines Notizbuchs + Datendateien im selben Ordner für Studenten)

Ist es zumindest garantiert, dass, wenn Sie ein Notebook in einem neuen Notebook-Server öffnen und implizit einen Kernel starten, indem Sie einen Code ausführen, dieser pwd den Ordner erhält, in dem sich die ipynb-Datei befindet?

Nein.

Es ist nicht garantiert, dass sich der Kernel auf derselben Maschine wie die ipynb befindet, es ist nicht einmal garantiert, dass die ipynb-Datei überhaupt existiert, existieren wird, eindeutig ist oder einen eindeutigen Pfad hat oder sogar eine Datei ist/sein wird. Beispiel: Zusammenarbeit in Echtzeit auf Google Drive.

Ich glaube ich habe meine Frage nicht gut genug formuliert. 200 Schüler werden eine Python-Umgebung einrichten, die meisten durch die Installation von Anaconda auf ihren eigenen Laptops. Ich werde ihnen die Computerübung als Notizbuch und Datendateien in einem Ordner übergeben. Einer von ihnen könnte das Notebook in der Postgres-DB speichern, zwei könnten den Kernel auf einem anderen Computer als ihrem Laptop ausführen, auf dem sie das Notebook haben. Drei Studenten werden gemeinsam eine Echtzeit-Zusammenarbeit auf Google Drive einrichten. Sechs Schüler werden etwas anderes tun, was Sie bisher vielleicht erwähnt haben oder nicht. Ich denke hauptsächlich an die 190 Studenten, die den Anweisungen vernünftig folgen, den Ordner auf ihrem eigenen Laptop (Windows, OS X oder Linux) entpacken, einen Notebook-Server auf dem _gleichen_ Laptop starten (entweder mit dem Notebook-Server-Explorer oder Doppelklicken Sie auf die Notebook-Datei) und lassen Sie implizit einen neuen Kernel starten (wieder auf demselben Laptop), indem Sie die erste Zelle ausführen. Die Frage ist, ob cwd für _diese_ Studenten funktioniert. Kommen etwa 15 Studenten in mein Büro, weil os.getcwd() nicht funktioniert hat, oder sollte ich eher mit 50-100 rechnen?

Ich denke hauptsächlich an die 190 Studenten, die den Anweisungen vernünftig folgen, den Ordner auf ihrem eigenen Laptop entpacken (Windows, OS X oder Linux), einen Notebook-Server auf demselben Laptop starten (entweder mit dem Notebook-Server-Explorer oder Doppelklicken Sie auf die Notebook-Datei) und lassen Sie implizit einen neuen Kernel starten (wieder auf demselben Laptop), indem Sie die erste Zelle ausführen.

Ja, die Verwendung von os.cwd() oder sogar c = !cwd funktioniert für diese Benutzer; und ich denke, in Ihrem Kontext ist es in Ordnung, sie darum zu bitten. Aber als _allgemeiner_ Anwendungsfall ist das nicht der Fall. Wir werden auch versuchen, bei der Angabe von Dingen in diesem Bugtracker vorsichtig zu sein, da dies als ausdrückliche Befürwortung dieser Methode durchgehen kann. Und wir kennen Leute, die dazu neigten, nicht gründlich zu lesen.

Fair genug, vielen Dank für Ihre Sorge um eine präzise Kommunikation.

Wenn das Skript zum ersten Mal in einer Arbeitsmappe ausgeführt wird und bevor es geändert wird, ist os.cwd() das Notebook-Verzeichnis.
Was ich also oft in meinem Code verwende, ist

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.

Wie es scheint, wollen die meisten Benutzer hier nicht wirklich auf den "Pfad des Notebooks" zugreifen, was auch immer das in einer bestimmten Bereitstellung bedeuten mag, sondern auf Ressourcen zugreifen, die diesem Notebook zugeordnet sind, so dass die Einzelheiten des Einsatzes werden abstrahiert.

Offensichtlich ist die Verteilung von Notizbüchern zusammen mit zugehörigen Daten ein allgemeiner und breiter Anwendungsfall. Vielleicht ist ein abstrakter Mechanismus für den Zugriff auf Ressourcen innerhalb eines Kernels erforderlich? Es wäre dann die Verantwortung der Bereitstellung (dh der Notebook-Serverinstallation), diese Ressourcenzugriffs-API ordnungsgemäß einzurichten, möglicherweise mit Hilfe einiger Metadaten aus dem Notebook? Dann könnte der lokale Notebook-Server standardmäßig diese Ressourcen tatsächlich von einem Pfad relativ zum Notebook bereitstellen. Andere Bereitstellungen bieten möglicherweise eine separate Schnittstelle (z. B. eine Upload-Methode oder eine URL, die auf Ressourcen verweist) oder unterstützen die Schnittstelle einfach überhaupt nicht.

Es könnte jetzt zu spät sein, aber es hört sich so an, als könnte Colaboratory Ihre Arbeit hier unterstützen:
https://colab.research.google.com/notebooks/welcome.ipynb

Es gibt eine Variable namens "_dh", die beim Start des Notebooks in die Globals eingefügt wird. Es scheint, dass dies das Verzeichnis des Notebooks ist, obwohl ich nicht nach Dokumentation dazu gesucht habe. Bei mir funktioniert es aber gerade.

Ähnlich der Lösung von @SurealCereal von:

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

Ich habe dies direkt nach meinen Importen verwendet:

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

Irgendetwas an dem Wort „Fehler“ lässt mich zweimal nachdenken, bevor ich an seiner Position oder Existenz herumspiele.

Alternative:

if 'workbookDir' not in globals():

ist etwas besser lesbar.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen