306 votes

Que signifie/fait la variable __file__ ?

import os

A = os.path.join(os.path.dirname(__file__), '..')

B = os.path.dirname(os.path.realpath(__file__))

C = os.path.abspath(os.path.dirname(__file__))

J'ai l'habitude de les câbler avec le chemin réel. Mais il y a une raison pour ces instructions qui déterminent le chemin au moment de l'exécution, et j'aimerais vraiment comprendre la raison pour laquelle le chemin est déterminé. os.path pour que je puisse commencer à l'utiliser.

260voto

paxdiablo Points 341644

Lorsqu'un module est chargé depuis un fichier en Python, __file__ est réglé sur sa trajectoire. Vous pouvez ensuite l'utiliser avec d'autres fonctions pour trouver le répertoire dans lequel se trouve le fichier.

Prenez vos exemples un par un :

A = os.path.join(os.path.dirname(__file__), '..')
# A is the parent directory of the directory where program resides.

B = os.path.dirname(os.path.realpath(__file__))
# B is the canonicalised (?) directory where the program resides.

C = os.path.abspath(os.path.dirname(__file__))
# C is the absolute path of the directory where the program resides.

Vous pouvez voir les différentes valeurs renvoyées par ces derniers ici :

import os
print(__file__)
print(os.path.join(os.path.dirname(__file__), '..'))
print(os.path.dirname(os.path.realpath(__file__)))
print(os.path.abspath(os.path.dirname(__file__)))

et assurez-vous que vous l'exécutez à partir de différents emplacements (tels que ./text.py , ~/python/text.py et ainsi de suite) pour voir quelle différence cela fait.

81voto

Derek Litz Points 3074

Je veux d'abord dissiper une certaine confusion. __file__ n'est pas un joker, mais un attribut. Les attributs et méthodes à double trait de soulignement sont considérés comme "spéciaux" par convention et servent un objectif particulier.

http://docs.python.org/reference/datamodel.html présente un grand nombre de méthodes et d'attributs spéciaux, mais pas tous.

Dans ce cas __file__ est un attribut d'un module (un objet module). En Python, un .py est un module. Donc import amodule aura un attribut de __file__ ce qui signifie des choses différentes dans des circonstances différentes.

Tiré de la documentation :

__file__ est le nom du chemin du fichier à partir duquel le module a été chargé, s'il a été chargé à partir d'un fichier. L'adresse __file__ n'est pas présent pour les modules C qui sont liés statiquement à l'interpréteur ; pour modules d'extension chargés dynamiquement à partir d'une bibliothèque partagée, il s'agit du nom de chemin de la bibliothèque partagée. nom de chemin du fichier de la bibliothèque partagée.

Dans votre cas, le module accède à son propre fichier __file__ dans l'espace de nom global.

Pour voir cela en action, essayez :

# file: test.py

print globals()
print __file__

Et courez :

python test.py

{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__file__':
 'test_print__file__.py', '__doc__': None, '__package__': None}
test_print__file__.py

25voto

Sudhir Points 50854

Par le documentation :

__file__ est le nom du chemin d'accès au fichier à partir duquel le module a été créé. chargé, s'il a été chargé à partir d'un fichier. L'adresse __file__ n'est pas pour les modules C qui sont liés statiquement à l'interpréteur ; pour les modules d'extension chargés dynamiquement à partir d'une bibliothèque partagée, il est le nom de chemin du fichier de la bibliothèque partagée.

et également :

__file__ doit être le "chemin" du fichier, à moins que le module ne soit intégré (et donc listé dans sys.builtin_module_names ), auquel cas l'attribut n'est pas défini.

21voto

aderchox Points 158

Je vais juste ajouter une note rapide ici (en répondant principalement au titre de la question plutôt qu'à sa description) concernant un changement qui peut dérouter certaines personnes. Depuis Python 3.4, il y a eu un léger changement dans la façon dont la fonction __file__ se comporte :

  • Il est défini comme le chemin relatif du module dans lequel il est utilisé, si ce module est exécuté directement.
  • Sinon, il est défini comme le chemin absolu du fichier.

Module __file__ (et les valeurs associées) doivent désormais toujours contenir des chemins absolus par défaut, à la seule exception de l'attribut __main__.__file__ lorsqu'un script a été exécuté directement en utilisant un chemin relatif. (Contribution de Brett Cannon dans numéro 18416 .)

Exemple :

Appeler le module x directement et le module y indirectement :

# x.py:
from pathlib import Path
import y
print(__file__)
print(Path(__file__))
print(Path(__file__).resolve())

# y.py:
from pathlib import Path
print(__file__)
print(Path(__file__))

Running python3 x.py produira un résultat :

/home/aderchox/mytest/y.py                                                                                                                       
/home/aderchox/mytest/y.py                                                                                                                       
x.py                                                                                                                                             
x.py                                                                                                                                             
/home/aderchox/mytest/x.py

16voto

sdolan Points 15572

Utilisation de __file__ combinée à divers os.path modules laisse tous les chemins relatifs à l'emplacement du répertoire du module actuel. Cela permet à vos modules/projets d'être portables sur d'autres machines.

Dans votre projet, vous le faites :

A = '/Users/myname/Projects/mydevproject/somefile.txt'

puis essayez de le déployer sur votre serveur avec un répertoire de déploiements du type /home/web/mydevproject/ alors votre code ne sera pas capable de trouver les chemins correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X