Python NameError: el nombre global '__file__' no está definido

112

Cuando ejecuto este código en Python 2.7, aparece este error:

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

el código es:

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
fuente

Respuestas:

134

Este error se produce cuando agrega esta línea os.path.join(os.path.dirname(__file__))en el shell interactivo de Python.

Python Shellno detecta la ruta del archivo actual __file__y está relacionada con la filepathque agregó esta línea

Por lo que debe escribir esta línea os.path.join(os.path.dirname(__file__))en file.py. y luego ejecutar python file.py, funciona porque toma su ruta de archivo.

Nilesh
fuente
8
exactamente mi experiencia. pero ¿cómo hacer que funcione dentro de un caparazón?
s2t2
1
Pero para ejecutar file.pydesde un script, lo colocaría en el mismo directorio que su script, por ejemplo. Por lo tanto, debe moverse a este directorio antes de ejecutar file.py... Así que aún se busca algo mejor.
ztyh
¿Entonces Emacs usa un shell interactivo cuando Cc Cp? Python-shell. ¿Hay alguna forma de usar este shell como si fuera un terminal que ejecuta el archivo? Hay 3 opciones para ejecutar el shell: CMD DEDICATED SHOW ¿Alguno de ellos haría esto?
sinekonata
18

Tuve el mismo problema con PyInstaller y Py2exe, así que encontré la resolución en las preguntas frecuentes de cx-freeze.

Cuando use su script desde la consola o como una aplicación, las funciones a continuación le entregarán la "ruta de ejecución", no la "ruta real del archivo":

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

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

Tu línea anterior (pregunta inicial):

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

Sustituya su línea de código con el siguiente fragmento.

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 el código anterior, puede agregar su aplicación a la ruta de su sistema operativo, puede ejecutarla en cualquier lugar sin el problema de que su aplicación no puede encontrar sus archivos de datos / configuración.

Probado con Python:

  • 3.3.4
  • 2.7.13
Kwuite
fuente
12

¡cambie sus códigos de la siguiente manera! esto funciona para mi. '

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
fuente
7
Creo que en realidad estás usando os.getcwd(), según el documento , y no "__file__"tiene sentido.
Davidlatwe
5
¿Por qué esto tiene votos positivos? ¿Cuánta gente tomó esto, y debido a que se deshizo de una excepción no manejada, asumieron que era correcto? Esta no es una solución correcta, gente . Lo que hace es decir que tiene un archivo llamado literalmente " __file__" y antepone en qué carpeta podría estar si existiera.
Todd
11

Me he encontrado con casos en los __file__que no funciona como se esperaba. Pero lo siguiente no me ha fallado hasta ahora:

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

Esto es lo más parecido a un Python análogo a C's __FILE__.

El comportamiento de Python __file__es muy diferente a la de C __FILE__. La versión C le dará la ruta original del archivo fuente. Esto es útil para registrar errores y saber qué archivo fuente tiene el error.

Python __file__solo le da el nombre del archivo que se está ejecutando actualmente, lo que puede no ser muy útil en la salida del registro.

Todd
fuente
2
Esto funciona también cuando Python está incrustado en otra aplicación
sdaau
He tenido más suerte con esto que con el os.path.dirname(os.path.realpath(...))método.
Mr. S
1
Esta debería ser la mejor respuesta.
183.amir
9

¿Utiliza el intérprete interactivo? Puedes usar

sys.argv[0]

Debería leer: ¿Cómo obtengo la ruta del archivo ejecutado actual en Python?

Eloims
fuente
fd = os.path.dirname (os.path.realpath ( archivo )) nd imprimiéndolo impreso ... / .. / folder1 / but cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> imprimir impresiones cwd ../../
bruceparker
7
esto le dará la ruta al pitón binario que lanzó el shell, NO el directorio de trabajo actual
hobs
debería ser en argv[1]lugar deargv[0]
plustar
9

Lo resolví tratando el archivo como una cadena, es decir, poniendo "__file__"(¡junto con las comillas!) En lugar de__file__

Esto funciona bien para mi:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
fuente
8
De hecho, esto funciona, pero no puedo entender por qué. ¿Por qué "__file__"entre comillas se trata de manera diferente que __file__sin comillas?
Gio
5
Porque no hace referencia a la variable global que falta. En su lugar, trata la cadena ' archivo ' como parte de la ruta.
JoshVarty
42
Esto no devuelve el directorio donde se encuentra el archivo , solo devuelve el directorio de trabajo actual (donde se llama a Python). -1
Xiangyu
8
Cualquier nombre de archivo servirá en lugar de "__file__". Ej realpath('nonexistentfile.whatever').
placas
35
Esta respuesta realmente debería eliminarse, ya que es incorrecta y engañosa. El hecho de que tenga una votación tan alta es bastante preocupante ...
Cas
6

Si todo lo que está buscando es obtener su directorio de trabajo actual, os.getcwd()obtendrá lo mismo os.path.dirname(__file__)siempre y cuando no haya cambiado el directorio de trabajo en otra parte de su código. os.getcwd()también funciona en modo interactivo.

Así se os.path.join(os.path.dirname(__file__)) convierte os.path.join(os.getcwd())

Andrew Fallgren
fuente
Este es un ganador
Shawn
1
Esta respuesta no es correcta . os.path.dirname(__file__)no informa lo mismo que os.getcwd(). Lo que le da es el nombre de directorio del archivo. Si resulta coincidir os.getcwd(), es simplemente una coincidencia.
Todd
4

Obtendrá esto si está ejecutando los comandos desde el shell de Python:

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

Debe ejecutar el archivo directamente, pasándolo como argumento al pythoncomando:

$ python somefile.py

En tu caso, debería ser python setup.py install

Burhan Khalid
fuente
2

Lo que puede hacer es utilizar lo siguiente

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

Tenga en cuenta aquí que el uso de la cadena de '__file__'hecho se refiere a la variable real __file__. Puede probar esto usted mismo, por supuesto.

La ventaja adicional de esta solución es la flexibilidad cuando ejecuta un script de forma parcialmente interactiva (por ejemplo, para probarlo / desarrollarlo) y puede ejecutarlo a través de la línea de comandos

zwep
fuente
Con respecto a su nota, si bien '__file__'es un nombre de variable válido, y su ifcondición será verdadera, os.path.realpath('__file__')devolverá una ruta falsa que se tratará '__file__'como si fuera el nombre del archivo. Si todo lo que necesita es su directorio principal vía os.path.dirname(), está bien, pero eso es un "truco". @zwep
Todd
Además, al hacer referencia __file__desde dentro de un archivo de origen, se obtendrá la ruta del archivo en el que se usa, no es lo mismo que os.getcwd(). No siempre será su wk_dirdirectorio o el del trabajo.
Todd
2

Si está ejecutando un archivo a través de la línea de comando, puede usar este truco

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

Esto funcionó para mí en la consola UnrealEnginePython, llamando py.exec myfile.py

crizCraig
fuente
1

Tuve el mismo problema en el cuaderno Jupyter. Mientras usaba 'os.path.split (os.path.realpath ( file ))', el cuaderno arrojaba un error.

Entonces usé ' archivo '. Funcionó perfectamente.

Ankit kaushik
fuente
0

Estoy teniendo exactamente el mismo problema y probablemente estoy usando el mismo tutorial . La definición de función:

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

Tiene errores, ya os.path.dirname(__file__)que no devolverá lo que necesita. Intente reemplazar 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()

Acabo de publicar a Andrew que el fragmento de código en los documentos actuales no funciona, con suerte, se corregirá.

ducin
fuente