python NameError: il nome globale '__file__' non è definito


112

Quando eseguo questo codice in Python 2.7, ottengo questo errore:

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

il codice è:

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='wehart@sandia.gov',
    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']
      )

Risposte:


134

Questo errore si verifica quando aggiungi questa riga os.path.join(os.path.dirname(__file__))nella shell interattiva di Python.

Python Shellnon rileva il percorso del file corrente in __file__ed è correlato al tuo filepathin cui hai aggiunto questa riga

Quindi si dovrebbe scrivere questa linea os.path.join(os.path.dirname(__file__))in file.py. e poi esegui python file.py, funziona perché prende il tuo percorso file.


8
esattamente la mia esperienza. ma come farlo funzionare all'interno di una shell?
s2t2

1
Ma per eseguire file.pyda uno script, lo metteresti nella stessa directory del tuo script, ad esempio. Quindi è necessario spostarsi in questa directory prima di eseguire file.py... Quindi si cerca ancora qualcosa di meglio.
ztyh

Quindi Emacs usa una shell interattiva quando si esegue Cc Cp? python-shell. C'è un modo per usare questa shell come se fosse un terminale che esegue il file? Ci sono 3 opzioni per eseguire la shell: CMD DEDICATED SHOW Uno di loro farebbe questo?
sinekonata

18

Ho avuto lo stesso problema con PyInstaller e Py2exe, quindi mi sono imbattuto nella risoluzione delle FAQ da cx-freeze.

Quando si utilizza lo script dalla console o come applicazione, le funzioni di seguito forniranno il "percorso di esecuzione", non il "percorso file effettivo":

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

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

La tua vecchia riga (domanda iniziale):

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

Sostituisci la tua riga di codice con il seguente frammento.

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)

Con il codice sopra puoi aggiungere la tua applicazione al percorso del tuo sistema operativo, puoi eseguirla ovunque senza il problema che la tua app non è in grado di trovare i suoi file di dati / configurazione.

Testato con Python:

  • 3.3.4
  • 2.7.13

12

cambia i tuoi codici come segue! per me funziona. `

os.path.dirname(os.path.abspath("__file__"))

7
Penso che tu stia effettivamente usando os.getcwd(), secondo doc , e non ha "__file__"senso.
davidlatwe

5
Perché questo ha voti positivi? Quante persone l'hanno preso e poiché si è sbarazzato di un'eccezione non gestita, hanno pensato che fosse corretto ?? Questa non è una soluzione corretta, persone . Quello che sta facendo è dire che hai un file chiamato letteralmente " __file__" e anteponi la cartella in cui potrebbe essere se esistesse!
Todd,

11

Mi sono imbattuto in casi in cui __file__non funziona come previsto. Ma quanto segue non mi ha deluso finora:

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

Questa è la cosa più vicina ad un analogo Python per C di __FILE__.

Il comportamento di Python __file__è molto diverso da quello di C __FILE__. La versione C ti darà il percorso originale del file sorgente. Ciò è utile per registrare gli errori e sapere quale file sorgente ha il bug.

Python __file__ti dà solo il nome del file attualmente in esecuzione, che potrebbe non essere molto utile nell'output del log.


2
Questo funziona anche quando python è incorporato in un'altra applicazione
sdaau

Ho avuto più fortuna con questo rispetto al os.path.dirname(os.path.realpath(...))metodo.
Mr. S

1
Questa dovrebbe essere la risposta migliore.
183.amir

9

Stai usando l'interprete interattivo? Puoi usare

sys.argv[0]

Dovresti leggere: Come ottengo il percorso del file attualmente eseguito in Python?


fd = os.path.dirname (os.path.realpath ( file )) e stamparlo stampato ... / .. / cartella1 / ma cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> stampa stampe cwd ../../
bruceparker

7
questo fornirà il percorso del python binario che ha lanciato la shell, NON la directory di lavoro corrente
hobs

dovrebbe essere argv[1]invece diargv[0]
plustar

9

L'ho risolto trattando il file come una stringa, cioè messo "__file__"(insieme alle virgolette!) Invece di__file__

Questo funziona bene per me:

wk_dir = os.path.dirname(os.path.realpath('__file__'))

8
Funziona davvero, ma non riesco a capire perché. Perché "__file__"tra virgolette viene trattato in modo diverso rispetto a __file__senza virgolette?
Gio

5
Perché non fa riferimento alla variabile globale mancante. Invece tratta la stringa " file " come parte del percorso.
JoshVarty

42
Questo non restituisce la directory in cui si trova il file , ma restituisce semplicemente la directory di lavoro corrente (dove viene chiamato python). -1
Xiangyu

8
Qualsiasi nome di file andrà al posto di "__file__". Ad esempio realpath('nonexistentfile.whatever').
piani cottura

35
Questa risposta dovrebbe davvero essere rimossa in quanto è errata e fuorviante. Il fatto che sia votato così bene è piuttosto preoccupante ...
Cas

6

Se tutto ciò che stai cercando è ottenere la tua directory di lavoro corrente os.getcwd()ti darà la stessa cosa os.path.dirname(__file__)fintanto che non hai cambiato la directory di lavoro altrove nel tuo codice. os.getcwd()funziona anche in modalità interattiva.

Così os.path.join(os.path.dirname(__file__)) diventa os.path.join(os.getcwd())


Questo è un vincitore
Shawn

1
Questa risposta non è corretta . os.path.dirname(__file__)non riporta la stessa cosa di os.getcwd(). Quello che ti dà è il nome della directory del file. Se questo risulta corrispondere os.getcwd()è solo una coincidenza.
Todd

4

Otterrai questo se stai eseguendo i comandi dalla shell python:

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

Devi eseguire il file direttamente, passandolo come argomento al pythoncomando:

$ python somefile.py

Nel tuo caso, dovrebbe essere davvero python setup.py install


2

Quello che puoi fare è usare quanto segue

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

Nota qui che l'uso della stringa '__file__'fa effettivamente riferimento alla variabile effettiva__file__ . Puoi testarlo tu stesso, naturalmente ..

Il vantaggio aggiuntivo di questa soluzione è la flessibilità quando si esegue uno script in parte in modo interattivo (ad esempio per testarlo / svilupparlo) e può essere eseguito tramite la riga di comando


Per quanto riguarda la tua nota, mentre '__file__'è un nome di variabile valido, e la tua ifcondizione sarà vera, os.path.realpath('__file__')restituirà un percorso falso che tratta '__file__'come se fosse il nome del file. Se tutto ciò di cui hai bisogno è la sua directory principale tramite os.path.dirname(), stai bene, ma è un "trucco". @zwep
Todd

Anche il riferimento __file__dall'interno di un file sorgente otterrà il percorso del file in cui è utilizzato - non è la stessa cosa di os.getcwd(). Non sarà sempre la tua wk_dirdirectory o quella di lavoro.
Todd

2

Se stai eseguendo un file tramite riga di comando, puoi usare questo hack

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

Questo ha funzionato per me nella console UnrealEnginePython, chiamando py.exec myfile.py


1

Ho avuto lo stesso problema nel notebook Jupyter. Mentre ho usato 'os.path.split (os.path.realpath ( file ))", il notebook generava un errore.

Ho quindi usato ' file '. Ha funzionato perfettamente.


0

Sto avendo esattamente lo stesso problema e sto usando probabilmente lo stesso tutorial . La definizione della funzione:

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

è bacato, poiché os.path.dirname(__file__)non restituirà ciò di cui hai bisogno. Prova a sostituire os.path.dirname(__file__)con os.path.dirname(os.path.abspath(__file__)):

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

Ho appena postato Andrew che lo snippet di codice nella documentazione corrente non funziona, si spera che venga corretto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.