web-dev-qa-db-fra.com

Comment obtenir le chemin du fichier actuellement exécuté en Python?

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:

sys.argv [0]

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.

__fichier__

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 contournement
  • Lorsque vous utilisez IDLE avec execute(), il n'y a pas d'attribut __file__.
  • OS X 10.6 où j'obtiens 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.

Mettre à jour

Voici le résultat d'un test:

Sortie de python a.py (sous Windows)

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

a.py

#! /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")

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

arbre

C:.
|   a.py
\---subdir
        b.py
170
sorin

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.

77
Daniel Stutzbach

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))
48
ArtOfWarfare

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__.

13
Garrett Berg

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.

6
Dale Hagglund

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))
5

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))

Comment ça marche:

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 fichier
  • getsourcefile(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? .

3
Edward

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).

2
Shule

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
2
Gavriel Cohen

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.

2
dgbcgx

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

0
Alex Cohn

Ma solution est:

import os
print(os.path.join(os.getcwd(), __file__))
0
ThienSuBS

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])
0
H. Kamran