Python NameError: le nom global '__file__' n'est pas défini

112

Lorsque j'exécute ce code en python 2.7, j'obtiens cette erreur:

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

le code est:

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
la source

Réponses:

134

Cette erreur survient lorsque vous ajoutez cette ligne os.path.join(os.path.dirname(__file__))dans le shell interactif python.

Python Shellne détecte pas le chemin du fichier actuel dans __file__et il est lié à votre filepathdans lequel vous avez ajouté cette ligne

Donc , vous devriez écrire cette ligne os.path.join(os.path.dirname(__file__))dans file.py. puis exécutez python file.py, cela fonctionne car il prend votre chemin de fichier.

Nilesh
la source
8
exactement mon expérience. mais comment le faire fonctionner dans un shell?
s2t2
1
Mais pour exécuter à file.pypartir d'un script, vous le mettriez dans le même répertoire que votre script par exemple. Vous devez donc vous déplacer dans ce répertoire avant de démarrer file.py... Donc quelque chose de mieux est encore recherché.
ztyh
Alors Emacs utilise un shell interactif lorsque vous Cc Cp? python-shell. Existe-t-il un moyen d'utiliser ce shell comme s'il s'agissait d'un terminal exécutant le fichier? Il y a 3 options pour exécuter le shell: CMD DEDICATED SHOW Est-ce que l'un d'eux ferait cela?
sinekonata le
18

J'ai eu le même problème avec PyInstaller et Py2exe, donc je suis tombé sur la résolution sur la FAQ de cx-freeze.

Lorsque vous utilisez votre script depuis la console ou en tant qu'application, les fonctions ci-dessous vous fourniront le "chemin d'exécution", et non le "chemin réel du fichier":

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

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

Votre ancienne ligne (question initiale):

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

Remplacez votre ligne de code par l'extrait de code suivant.

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)

Avec le code ci-dessus, vous pouvez ajouter votre application au chemin de votre système d'exploitation, vous pouvez l'exécuter n'importe où sans le problème que votre application est incapable de trouver ses fichiers de données / configuration.

Testé avec python:

  • 3.3.4
  • 2.7.13
Kwuite
la source
12

changez vos codes comme suit! ça marche pour moi. »

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
la source
7
Je pense que vous utilisez réellement os.getcwd(), selon le doc , et cela "__file__"n'a pas de sens.
davidlatwe
5
Pourquoi cela a-t-il des votes positifs? Que beaucoup de gens ont pris cela, et parce que cela a éliminé une exception non gérée, ils ont supposé que c'était correct ?? Ce n'est pas une bonne solution pour les gens . Ce qu'il fait, c'est dire que vous avez un fichier nommé littéralement, " __file__" et vous ajoutez dans quel dossier il pourrait se trouver s'il existait!
Todd le
11

J'ai rencontré des cas où __file__ne fonctionne pas comme prévu. Mais ce qui suit ne m'a pas laissé tomber jusqu'à présent:

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

Ceci est le plus proche d'un analogue Python C de __FILE__.

Le comportement de ce Python __file__est très différent de C de __FILE__. La version C vous donnera le chemin d'origine du fichier source. Ceci est utile pour consigner les erreurs et savoir quel fichier source a le bogue.

Python __file__ne vous donne que le nom du fichier en cours d'exécution, ce qui peut ne pas être très utile dans la sortie du journal.

Todd
la source
2
Cela fonctionne également lorsque python est intégré dans une autre application
sdaau
J'ai eu plus de chance avec ça qu'avec la os.path.dirname(os.path.realpath(...))méthode.
M. S
1
Cela devrait être la meilleure réponse.
183.amir
9

Utilisez-vous l'interprète interactif? Vous pouvez utiliser

sys.argv[0]

Vous devriez lire: Comment obtenir le chemin du fichier exécuté en cours en Python?

Eloims
la source
fd = os.path.dirname (os.path.realpath ( fichier )) nd l'imprimer imprimé ... / .. / folder1 / mais cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> impression cwd impressions ../../
bruceparker
7
cela donnera le chemin vers le python binaire qui a lancé le shell, PAS le répertoire de travail actuel
hobs
il devrait être argv[1]au lieu deargv[0]
plustar
9

Je l'ai résolu en traitant le fichier comme une chaîne, c'est-à-dire mis "__file__"(avec les guillemets!) Au lieu de__file__

Cela fonctionne bien pour moi:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
la source
8
Cela fonctionne en effet, mais je ne peux pas comprendre pourquoi. Pourquoi le "__file__"traitement entre guillemets est-il différent de celui __file__sans guillemets?
Gio
5
Parce qu'il ne fait pas référence à la variable globale manquante. Au lieu de cela, il traite la chaîne « fichier » comme faisant partie du chemin.
JoshVarty
42
Cela ne retourne pas le répertoire où se trouve le fichier , mais renvoie simplement le répertoire de travail actuel (où python est appelé). -1
Xiangyu
8
N'importe quel nom de fichier fera l'affaire à la place de "__file__". Par exemple realpath('nonexistentfile.whatever').
plaques de cuisson
35
Cette réponse devrait vraiment être supprimée car elle est incorrecte et trompeuse. Le fait qu'il soit si fortement voté est plutôt inquiétant ...
Cas
6

Si tout ce que vous cherchez est d'obtenir votre répertoire de travail actuel, vous obtiendrez os.getcwd()la même chose tant os.path.dirname(__file__)que vous n'avez pas changé le répertoire de travail ailleurs dans votre code. os.getcwd()fonctionne également en mode interactif.

Devient os.path.join(os.path.dirname(__file__)) ainsi os.path.join(os.getcwd())

Andrew Fallgren
la source
Ceci est un gagnant
Shawn
1
Cette réponse n'est pas correcte . os.path.dirname(__file__)ne rapporte pas la même chose que os.getcwd(). Ce qu'il vous donne est le nom de répertoire du fichier. Si cela correspond, os.getcwd()c'est simplement une coïncidence.
Todd
4

Vous obtiendrez ceci si vous exécutez les commandes depuis le shell python:

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

Vous devez exécuter le fichier directement, en le passant comme argument à la pythoncommande:

$ python somefile.py

Dans votre cas, cela devrait vraiment être python setup.py install

Burhan Khalid
la source
2

Ce que vous pouvez faire est d'utiliser les éléments suivants

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

Notez ici que l'utilisation de la chaîne '__file__'fait bien référence à la variable réelle __file__. Vous pouvez bien sûr tester cela vous-même.

Le bonus supplémentaire de cette solution est la flexibilité lorsque vous exécutez un script en partie de manière interactive (par exemple pour le tester / le développer), et pouvez l'exécuter via la ligne de commande

zwep
la source
Concernant votre note, while '__file__'est un nom de variable valide, et votre ifcondition sera vraie, os.path.realpath('__file__')retournera un faux chemin en traitant '__file__'comme s'il s'agissait du nom du fichier. Si tout ce dont vous avez besoin est son répertoire parent via os.path.dirname(), tout va bien - mais c'est un "hack". @zwep
Todd
Faire également référence à __file__partir d'un fichier source obtiendra le chemin du fichier dans lequel il est utilisé - ce n'est pas la même chose que os.getcwd(). Ce ne sera pas toujours votre wk_dir- ou votre répertoire de travail.
Todd
2

Si vous exécutez un fichier via la ligne de commande, vous pouvez utiliser ce 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

Cela a fonctionné pour moi dans la console UnrealEnginePython, en appelant py.exec myfile.py

crizCraig
la source
1

J'ai eu le même problème dans le notebook Jupyter. Alors que j'utilisais 'os.path.split (os.path.realpath ( file ))', le cahier lançait une erreur.

J'ai donc utilisé « fichier ». Cela a parfaitement fonctionné.

Ankit kaushik
la source
0

J'ai exactement le même problème et j'utilise probablement le même tutoriel . La définition de la fonction:

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

est bogué, car os.path.dirname(__file__)ne retournera pas ce dont vous avez besoin. Essayez de remplacer os.path.dirname(__file__)par os.path.dirname(os.path.abspath(__file__)):

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

Je viens de signaler à Andrew que l'extrait de code dans les documents actuels ne fonctionne pas, j'espère qu'il sera corrigé.

ducine
la source