python NameError: Der globale Name '__file__' ist nicht definiert

111

Wenn ich diesen Code in Python 2.7 ausführe, wird folgende Fehlermeldung angezeigt:

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 30, in <module>
    long_description = read('README.txt'),
  File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 19, in read
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
NameError: global name '__file__' is not defined

Code ist:

import os
from setuptools import setup


def read(*rnames):
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()


setup(name="pyutilib.subprocess",
    version='3.5.4',
    maintainer='William E. Hart',
    maintainer_email='[email protected]',
    url = 'https://software.sandia.gov/svn/public/pyutilib/pyutilib.subprocess',
    license = 'BSD',
    platforms = ["any"],
    description = 'PyUtilib utilites for managing subprocesses.',
    long_description = read('README.txt'),
    classifiers = [
        'Development Status :: 4 - Beta',
        'Intended Audience :: End Users/Desktop',
        'License :: OSI Approved :: BSD License',
        'Natural Language :: English',
        'Operating System :: Microsoft :: Windows',
        'Operating System :: Unix',
        'Programming Language :: Python',
        'Programming Language :: Unix Shell',
        'Topic :: Scientific/Engineering :: Mathematics',
        'Topic :: Software Development :: Libraries :: Python Modules'],
      packages=['pyutilib', 'pyutilib.subprocess', 'pyutilib.subprocess.tests'],
      keywords=['utility'],
      namespace_packages=['pyutilib'],
      install_requires=['pyutilib.common', 'pyutilib.services']
      )
Kaibing Yang
quelle

Antworten:

134

Dieser Fehler tritt auf, wenn Sie diese Zeile os.path.join(os.path.dirname(__file__))in der interaktiven Python-Shell anhängen .

Python ShellDer aktuelle Dateipfad in wird nicht erkannt __file__und hängt mit dem zusammen, filepathin dem Sie diese Zeile hinzugefügt haben

Also solltest du diese Zeile os.path.join(os.path.dirname(__file__))einschreiben file.py. und dann ausführen python file.py, es funktioniert, weil es Ihren Dateipfad nimmt.

Nilesh
quelle
8
genau meine Erfahrung. aber wie bringt man es dazu, in einer Shell zu funktionieren?
s2t2
1
Um file.pyein Skript auszuführen , müssen Sie es beispielsweise im selben Verzeichnis wie Ihr Skript ablegen. Sie müssen also vor dem Ausführen in dieses Verzeichnis wechseln file.py... Es wird also immer noch nach etwas Besserem gesucht.
Ztyh
Also verwendet Emacs eine interaktive Shell, wenn Sie Cc Cp? Python-Shell. Gibt es eine Möglichkeit, diese Shell so zu verwenden, als wäre sie ein Terminal, auf dem die Datei ausgeführt wird? Es gibt 3 Optionen zum Ausführen der Shell: CMD DEDICATED SHOW Würde einer von ihnen dies tun?
Sinuskonata
18

Ich hatte das gleiche Problem mit PyInstaller und Py2exe, daher bin ich auf die Auflösung in den FAQ von cx-freeze gestoßen.

Wenn Sie Ihr Skript über die Konsole oder als Anwendung verwenden, liefern Ihnen die folgenden Funktionen den "Ausführungspfad" und nicht den "tatsächlichen Dateipfad":

print(os.getcwd())
print(sys.argv[0])
print(os.path.dirname(os.path.realpath('__file__')))

Quelle:
http://cx-freeze.readthedocs.org/en/latest/faq.html

Ihre alte Zeile (erste Frage):

def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

Ersetzen Sie Ihre Codezeile durch das folgende Snippet.

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)

Mit dem obigen Code können Sie Ihre Anwendung zum Pfad Ihres Betriebssystems hinzufügen und sie überall ausführen, ohne das Problem, dass Ihre App ihre Daten- / Konfigurationsdateien nicht finden kann.

Getestet mit Python:

  • 3.3.4
  • 2.7.13
Kwuite
quelle
11

Ändern Sie Ihre Codes wie folgt! Für mich geht das. `

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
quelle
7
Ich denke, Sie verwenden tatsächlich os.getcwd(), laut doc , und das "__file__"ist bedeutungslos.
Davidlatwe
5
Warum hat dies positive Stimmen? Dass viele Leute das genommen haben und weil es eine unbehandelte Ausnahme beseitigt hat, haben sie angenommen, dass es richtig ist? Dies ist keine richtige Lösung, Leute . Es heißt, Sie haben eine Datei mit dem wörtlichen Namen " __file__" und stellen vor, in welchem ​​Ordner sie sich befinden könnte, wenn sie existiert!
Todd
11

Ich bin auf Fälle gestoßen, in denen __file__es nicht wie erwartet funktioniert. Aber Folgendes hat mich bisher nicht enttäuscht:

import inspect
src_file_path = inspect.getfile(lambda: None)

Dies kommt einem Python-Analogon zu C am nächsten __FILE__.

Das Verhalten von Pythons __file__ist ganz anders als C ist __FILE__. Die C-Version gibt Ihnen den ursprünglichen Pfad der Quelldatei. Dies ist nützlich, um Fehler zu protokollieren und zu wissen, welche Quelldatei den Fehler aufweist.

Python __file__gibt Ihnen nur den Namen der aktuell ausgeführten Datei an, was bei der Protokollausgabe möglicherweise nicht sehr nützlich ist.

Todd
quelle
2
Dies funktioniert auch, wenn Python in eine andere Anwendung eingebettet ist
Sdaau
Ich hatte damit mehr Glück als mit der os.path.dirname(os.path.realpath(...))Methode.
Mr. S
1
Dies sollte die beste Antwort sein.
183.amir
9

Verwenden Sie den interaktiven Interpreter? Sie können verwenden

sys.argv[0]

Sie sollten lesen: Wie erhalte ich den Pfad der aktuell ausgeführten Datei in Python?

Eloims
quelle
fd = os.path.dirname (os.path.realpath ( Datei )) und Drucken gedruckt ... / .. / folder1 / aber cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> drucken cwd druckt ../../
bruceparker
7
Dies gibt den Pfad zu der binären Python, die die Shell gestartet hat, NICHT das aktuelle Arbeitsverzeichnis
Kochfelder
es sollte argv[1]stattargv[0]
plustar
9

Ich habe es gelöst, indem ich die Datei als Zeichenfolge behandelt habe, dh "__file__"(zusammen mit den Anführungszeichen!) Statt__file__

Das funktioniert gut für mich:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
quelle
8
Das funktioniert zwar, aber ich kann mir nicht vorstellen, warum. Warum werden "__file__"zwischen Anführungszeichen anders behandelt als __file__ohne Anführungszeichen?
Gio
5
Weil es nicht auf die fehlende globale Variable verweist. Stattdessen wird die Zeichenfolge ' Datei ' als Teil des Pfads behandelt.
JoshVarty
42
Dies gibt nicht das Verzeichnis zurück, in dem sich die Datei befindet, sondern nur das aktuelle Arbeitsverzeichnis (in dem Python aufgerufen wird). -1
Xiangyu
8
Jeder Dateiname wird anstelle von "__file__". ZB realpath('nonexistentfile.whatever').
Kochfelder
35
Diese Antwort sollte wirklich entfernt werden, da sie falsch und irreführend ist. Die Tatsache, dass es so hoch bewertet wird, ist ziemlich besorgniserregend ...
Cas
6

Wenn Sie nur nach Ihrem aktuellen Arbeitsverzeichnis suchen, erhalten os.getcwd()Sie dasselbe, os.path.dirname(__file__)solange Sie das Arbeitsverzeichnis an keiner anderen Stelle in Ihrem Code geändert haben. os.getcwd()funktioniert auch im interaktiven Modus.

So os.path.join(os.path.dirname(__file__)) wird os.path.join(os.getcwd())

Andrew Fallgren
quelle
Dies ist ein Gewinner
Shawn
1
Diese Antwort ist nicht richtig . os.path.dirname(__file__)meldet nicht dasselbe wie os.getcwd(). Was es Ihnen gibt, ist der Verzeichnisname der Datei. Wenn sich herausstellt, dass das passt, ist os.getcwd()es nur ein Zufall.
Todd
4

Sie erhalten dies, wenn Sie die Befehle über die Python-Shell ausführen:

>>> __file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__file__' is not defined

Sie müssen die Datei direkt ausführen, indem Sie sie als Argument an den pythonBefehl übergeben:

$ python somefile.py

In deinem Fall sollte es wirklich so sein python setup.py install

Burhan Khalid
quelle
2

Was Sie tun können, ist Folgendes zu verwenden

import os
if '__file__' in vars():
    wk_dir = os.path.dirname(os.path.realpath('__file__'))
else:
    print('We are running the script interactively')

Beachten Sie hier, dass sich die Verwendung der Zeichenfolge '__file__'tatsächlich auf die tatsächliche Variable bezieht __file__. Sie können dies natürlich selbst testen.

Der zusätzliche Vorteil dieser Lösung ist die Flexibilität, wenn Sie ein Skript teilweise interaktiv ausführen (z. B. um es zu testen / zu entwickeln) und es über die Befehlszeile ausführen können

zwep
quelle
Wenn es sich bei Ihrer Notiz '__file__'um einen gültigen Variablennamen handelt und Ihre ifBedingung erfüllt ist, os.path.realpath('__file__')wird ein gefälschter Pfad zurückgegeben, der so behandelt wird, '__file__'als wäre es der Name der Datei. Wenn Sie nur das übergeordnete Verzeichnis über benötigen, ist os.path.dirname()alles in Ordnung - aber das ist ein "Hack". @zwep
Todd
Wenn Sie auch __file__aus einer Quelldatei heraus referenzieren, erhalten Sie den Pfad der Datei, in der sie verwendet wird - es ist nicht dasselbe wie os.getcwd(). Es wird nicht immer Ihr wk_dir- oder Arbeitsverzeichnis sein.
Todd
2

Wenn Sie eine Datei über die Befehlszeile ausführen, können Sie diesen Hack verwenden

import traceback

def get_this_filename():
    try:
        raise NotImplementedError("No error")
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        filename = traceback.extract_tb(exc_traceback)[-1].filename
    return filename

Dies funktionierte für mich in der UnrealEnginePython-Konsole beim Aufrufen py.exec myfile.py

crizCraig
quelle
1

Ich hatte das gleiche Problem im Jupyter-Notizbuch. Während ich 'os.path.split (os.path.realpath ( file ))' verwendet habe, hat das Notizbuch einen Fehler ausgegeben .

Ich habe also ' Datei ' verwendet. Es hat perfekt funktioniert.

Ankit kaushik
quelle
0

Ich habe genau das gleiche Problem und benutze wahrscheinlich das gleiche Tutorial . Die Funktionsdefinition:

def read(*rnames):
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

ist fehlerhaft, da os.path.dirname(__file__)wird nicht zurückgeben, was Sie brauchen. Versuchen Sie ersetzen os.path.dirname(__file__)mit os.path.dirname(os.path.abspath(__file__)):

def read(*rnames):
    return open(os.path.join(os.path.dirname(os.path.abspath(__file__)), *rnames)).read()

Ich habe gerade Andrew gepostet, dass das Code-Snippet in aktuellen Dokumenten nicht funktioniert, hoffentlich wird es korrigiert.

Ducin
quelle