Cela peut sembler une question de débutant, mais ce n’est pas le cas. Certaines approches courantes ne fonctionnent pas dans tous les cas:
Cela signifie que vous devez utiliser path = os.path.abspath(os.path.dirname(sys.argv[0]))
, mais cela ne fonctionne pas si vous utilisez un autre script Python dans un autre répertoire, ce qui peut arriver dans la vie réelle.
Cela signifie utiliser path = os.path.abspath(os.path.dirname(__file__))
, mais j'ai constaté que cela ne fonctionnait pas:
py2exe
n'a pas d'attribut __file__
, mais il existe un solution de contournementexecute()
, il n'y a pas d'attribut __file__
.NameError: global name '__file__' is not defined
Questions connexes avec des réponses incomplètes:
Je recherche une solution generic, qui conviendrait dans tous les cas d'utilisation décrits ci-dessus.
Voici le résultat d'un test:
a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz
b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz
#! /usr/bin/env python
import os, sys
print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print
execfile("subdir/b.py")
#! /usr/bin/env python
import os, sys
print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print
C:.
| a.py
\---subdir
b.py
Vous ne pouvez pas déterminer directement l'emplacement du script principal en cours d'exécution. Après tout, parfois, le script ne venait pas du tout d'un fichier. Par exemple, cela pourrait provenir de l'interpréteur interactif ou du code généré dynamiquement stocké uniquement en mémoire.
Cependant, vous pouvez déterminer de manière fiable l'emplacement d'un module, car les modules sont toujours chargés à partir d'un fichier. Si vous créez un module avec le code suivant et le placez dans le même répertoire que votre script principal, le script principal peut importer le module et l'utiliser pour se localiser.
chemin_cours/module_locateur.py:
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
chemin_proche/main.py:
import module_locator
my_path = module_locator.module_path()
Si vous avez plusieurs scripts principaux dans des répertoires différents, vous aurez peut-être besoin de plusieurs copies de module_locator.
Bien sûr, si votre script principal est chargé par un autre outil qui ne vous permet pas d'importer des modules co-localisés avec votre script, vous n'avez pas de chance. Dans de tels cas, les informations recherchées n'existent tout simplement pas dans votre programme. Votre meilleur choix serait de déposer un bogue avec les auteurs de l’outil.
D'abord, vous devez importer de inspect
et os
from inspect import getsourcefile
from os.path import abspath
Ensuite, partout où vous voulez trouver le fichier source, utilisez simplement
abspath(getsourcefile(lambda:0))
Je rencontrais un problème similaire, et je pense que cela pourrait résoudre le problème:
def module_path(local_function):
''' returns the module path without the use of __file__. Requires a function defined
locally in the module.
from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
return os.path.abspath(inspect.getsourcefile(local_function))
Cela fonctionne pour les scripts réguliers et en veille. Tout ce que je peux dire, c'est l'essayer pour les autres!
Mon utilisation typique:
from toolbox import module_path
def main():
pass # Do stuff
global __modpath__
__modpath__ = module_path(main)
Maintenant, j'utilise __modpath__ au lieu de __file__.
La réponse courte est que il n’existe aucun moyen garanti d’obtenir les informations souhaitées}, mais il existe des heuristiques qui fonctionnent presque toujours dans la pratique. Vous pourriez regarder à Comment trouver l'emplacement de l'exécutable en C?. Il aborde le problème du point de vue du C, mais les solutions proposées sont facilement transcrites en Python.
cette solution est robuste même dans les exécutables
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
Voir ma réponse à la question Importation de modules du dossier parent pour obtenir des informations connexes, y compris pourquoi ma réponse n’utilise pas la variable non fiable __file__
. Cette solution simple doit être compatible avec différents systèmes d'exploitation, car les modules os
et inspect
font partie de Python.
Tout d’abord, vous devez importer des parties des modules inspect et os.
from inspect import getsourcefile
from os.path import abspath
Ensuite, utilisez la ligne suivante partout où cela est nécessaire dans votre code Python:
abspath(getsourcefile(lambda:0))
A partir du module intégré os
(description ci-dessous), l'outil abspath
est importé.
Les routines de système d'exploitation pour Mac, NT ou Posix selon le système sur lequel nous sommes.
Ensuite, getsourcefile
(description ci-dessous) est importé du module intégré inspect
.
Obtenez des informations utiles à partir d'objets Python en direct.
abspath(path)
renvoie la version absolue/complète d'un chemin de fichiergetsourcefile(lambda:0)
récupère en quelque sorte le fichier source interne de l'objet fonction lambda, renvoie donc '<pyshell#nn>'
dans le shell Python ou renvoie le chemin du fichier du code Python en cours d'exécution.Si vous utilisez abspath
sur le résultat de getsourcefile(lambda:0)
, vous devez vous assurer que le chemin du fichier généré est le chemin complet du fichier Python.
Cette solution expliquée était basée à l'origine sur le code de la réponse de Comment obtenir le chemin du fichier actuellement exécuté en Python? .
Cela devrait faire l'affaire de façon multi-plateforme (tant que vous n'utilisez pas l'interprète ou autre chose):
import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0]
est le répertoire dans lequel se trouve votre script d'appel (le premier endroit où il recherche les modules à utiliser par ce script). Nous pouvons prendre le nom du fichier lui-même à la fin de sys.argv[0]
(ce que j’ai fait avec os.path.basename
). os.path.join
les colle simplement de manière multiplateforme. os.path.realpath
s'assure simplement que si nous obtenons des liens symboliques avec des noms différents du script lui-même, nous obtenons toujours le nom réel du script.
Je n'ai pas de Mac donc, je n'ai pas testé cela sur un. S'il vous plaît laissez-moi savoir si cela fonctionne, comme il semble qu'il devrait. J'ai testé cela sous Linux (Xubuntu) avec Python 3.4. Notez que de nombreuses solutions à ce problème ne fonctionnent pas sur les Mac (car j'ai entendu dire que __file__
n'est pas présent sur les Mac).
Notez que si votre script est un lien symbolique, il vous donnera le chemin du fichier vers lequel il est lié (et non le chemin du lien symbolique).
Vous pouvez utiliser Path
à partir du module pathlib
:
from pathlib import Path
# ...
Path(__file__)
Vous pouvez utiliser call to parent
pour aller plus loin dans le chemin:
Path(__file__).parent
Vous avez simplement appelé:
path = os.path.abspath(os.path.dirname(sys.argv[0]))
au lieu de:
path = os.path.dirname(os.path.abspath(sys.argv[0]))
abspath()
vous donne le chemin absolu de sys.argv[0]
(le nom du fichier dans lequel se trouve votre code) et dirname()
renvoie le chemin du répertoire sans le nom du fichier.
Si le code provient d'un fichier, vous pouvez obtenir son nom complet.
sys._getframe().f_code.co_filename
Vous pouvez également récupérer le nom de la fonction sous la forme f_code.co_name
Ma solution est:
import os
print(os.path.join(os.getcwd(), __file__))
Ajoutez simplement ce qui suit:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
Ou:
from sys import *
print(sys.argv[0])