__file__ existiert nicht in Jupyter Notebook

78

Ich bin auf einem Jupyter Notebook- Server (v4.2.2) mit Python 3.4.2 und möchte den globalen Namen verwenden __file__, da das Notebook von anderen Benutzern geklont wird und ich in einem Abschnitt Folgendes ausführen muss:

def __init__(self, trainingSamplesFolder='samples', maskFolder='masks'):
    self.trainingSamplesFolder = self.__getAbsPath(trainingSamplesFolder)
    self.maskFolder = self.__getAbsPath(maskFolder)

def __getAbsPath(self, path):
    if os.path.isabs(path):
        return path
    else:
        return os.path.join(os.path.dirname(__file__), path)

Die __getAbsPath(self, path)prüft , ob ein pathparam ein relativer oder absoluter Pfad ist und gibt die absolute Version path. So kann ich die zurückgegebenen pathspäter sicher verwenden.

Aber ich bekomme den Fehler

NameError: Name '__file__'ist nicht definiert

Ich habe online nach diesem Fehler gesucht und die "Lösung" gefunden, die ich besser verwenden sollte sys.argv[0], aber print(sys.argv[0])zurückgibt

/usr/local/lib/python3.4/dist-packages/ipykernel/__main__.py

Der richtige Ort für das Notebook sollte jedoch sein /home/ubuntu/notebooks/.

Vielen Dank für die Referenz. Wie erhalte ich den aktuellen IPython Notebook-Namen von Martijn Pieters (Kommentare)? Die letzte Antwort (nicht akzeptiert) passt perfekt zu meinen Anforderungen:

print(os.getcwd())

/ home / ubuntu / notebooks

Fabian
quelle
2
__file__gilt für Module und Python-Skripte , nicht für Notebooks. Die Antworten, die Sie gefunden haben, gelten hier nicht.
Martijn Pieters
3
Wie erhalte ich den aktuellen IPython Notebook-Namen, der relevanter aussieht?
Martijn Pieters

Antworten:

53

Wenn Sie den Pfad des Verzeichnisses abrufen möchten, in dem Ihr Skript ausgeführt wird, würde ich die Verwendung von empfehlen.

os.path.abspath('')

Vorteile

  • Es funktioniert mit Jupyter Notebook
  • Es funktioniert von REPL
  • Die Pathlib von Python 3.4 ist nicht erforderlich

Bitte beachten Sie, dass ein Szenario von __file__Vorteil ist, wenn Sie Python aus Verzeichnis A aufrufen, aber das Skript in Verzeichnis B ausführen. In diesem Fall geben die meisten anderen Methoden A und nicht B zurück. Für Jupyter notbook erhalten Sie jedoch immer einen Ordner für .ipynDatei anstelle des Verzeichnisses, von dem aus Sie gestartet haben jupyter notebook.

Shital Shah
quelle
2
Das funktioniert bei mir nicht. Es gibt mir stattdessen "Arbeitsverzeichnis", wenn ich ein Notizbuch mit Papiermühle betreibe.
Untidyhair
Das ist überraschend. In meinen Tests funktionieren alle 3 Szenarien. Könnte dies an der Papiermühle liegen (ich bin damit nicht vertraut)?
Shital Shah
3
@Shital, unordentliches Haar ist richtig. Dies funktioniert, wie der andere Vorschlag von mab unten, NICHT. Es gibt Ihnen nur die cwd.
Keim
18

__file__ Möglicherweise ist es für Sie nicht verfügbar, aber Sie können den aktuellen Ordner abrufen, in dem sich Ihr Notebook tatsächlich auf andere Weise befindet.

Es gibt Spuren in globalen Variablen. Wenn Sie aufrufen, werden globals()Sie feststellen _dh, dass der Schlüssel ein Element enthält , das Ihnen möglicherweise hilft. So habe ich es geschafft, die data.csvDatei zu laden, die sich im selben Ordner wie mein Notizbuch befindet:

import os

current_folder = globals()['_dh'][0]

# Calculating path to the input data
data_location = os.path.join(current_folder,'data.csv')
shytikov
quelle
2
Wow, herzlichen Glückwunsch @shytikov, Ihre Methode funktioniert wirklich und sollte die bevorzugte Antwort sein. Sie haben eine Methode gefunden, die die hässlichen JS-Hacks vermeidet. Vielen, vielen Dank. Nun, wenn wir einen Weg finden könnten, den Namen des Notizbuchs zu erhalten ...
Keim
Es sieht so aus, als ob dies in Notebook funktioniert, aber nicht in einem normalen Python-Interpreter (zumindest beim Import als Modul). Ich wechsle zwischen der Verwendung von Jupyter-Kerneln und einem normalen Python-Interpreter, daher brauche ich etwas, das auf beiden funktioniert. Ich denke, ich werde auf eine Umgebungsvariable zurückgreifen.
Kyle Barron
Dies funktioniert für mich sowohl in JupyterLab als auch in Pycharm, während die anderen Vorschläge dies nicht taten.
Aimfeld
16

Es ist nicht möglich, den Pfad zum Notizbuch zu finden. Möglicherweise finden Sie einen Weg, um es zu erhalten, der nur in einer Umgebung funktioniert (z. B. os.getcwd()), aber es funktioniert nicht unbedingt, wenn das Notebook auf eine andere Weise geladen wird.

Versuchen Sie stattdessen, das Notizbuch so zu schreiben, dass es seinen eigenen Pfad nicht kennen muss. Wenn Sie beispielsweise das pwd abrufen, sollten Sie schnell fehlschlagen / einen Fehler drucken, wenn dies nicht funktioniert, anstatt nur still zu versuchen, fortzufahren.

Siehe auch: https://github.com/ipython/ipython/issues/10123

Michael
quelle
Sie haben Recht, dass es nicht möglich ist, den Pfad zum Notizbuch mit os.getcwd () abzurufen. Dies bekommt nur die cwd. Wenn Sie dies im Notizbuch geändert haben und dann zu dieser Zelle zurückkehren, wird das Notizbuchverzeichnis nicht angezeigt. Dies ist ein großes Problem. Und nein, ich bin nicht der Meinung, dass Sie Ihr Skript so schreiben sollten, dass es nicht wissen muss, wo es sich befindet. Dafür gibt es sehr gute Gründe, z. B. eine Kopie an einen anderen Ort zu erstellen.
Keim
15

In modernem Python (v3.4 +) können wir pathlib verwenden , um das Verzeichnis des Notebooks abzurufen :

from pathlib import Path

cwd = Path().resolve()
# cwd == PosixPath('/path/to/this/jupyter/ipynb/file's/directory/')

# or this way, thanks @NunoAndré:
cwd = Path.cwd()
# cwd == PosixPath('/path/to/this/jupyter/ipynb/file's/directory/')



Aktualisieren

@ShitalShah Ich kann den von Ihnen gemeldeten Fehler nicht reproduzieren. Jupyter Notebook scheint gut zu funktionieren, unabhängig vom aktuellen Arbeitsverzeichnis, in dem die Anwendung gestartet wurde.

Beispiel: Datei ~/dir1/dir2/untitled.ipynbund Jupyter-Notizbuch gestartet in ~/dir1:

Jupyter-Notizbuch wurde in ~ / dir1 gestartet

Jupyter Notebook begann in ~/dir1/dir2:

Das Jupyter-Notizbuch wurde in ~ / dir1 / dir2 gestartet

mab
quelle
1
Leider wird dies nicht
funktionieren
@ShitalShah siehe die aktualisierte Antwort. Vielleicht können Sie klären, was das Problem ist, auf das Sie stoßen.
Mab
1
Bitte ignoriere meinen Kommentar. Sie haben Recht, dass dies sowohl in Jupyter Notebook als auch in REPL funktioniert, aber es gibt einen anderen Weg, für den Python 3.4 pathlib nicht erforderlich ist, und ich habe diese Antwort ebenfalls hinzugefügt.
Shital Shah
1
Pathhat eine Klassenmethode nur dafür:Path.cwd()
Nuno André
2
@mac, das funktioniert NICHT. Wenn Sie cwd in Ihrem Notizbuch ändern und diese Zelle erneut ausführen, erhalten Sie das neue cwd und nicht den Speicherort des Notbooks. Dies ist eine schmerzlich fehlende Funktion in Jupyter Notebook. Ich muss auf einen Hack mit Javascript zurückgreifen. Was für eine PITA.
Keim