Comment puis-je obtenir le chemin du fichier courant exécuté en Python?

cela peut sembler comme une question de débutant, mais il n'est pas. Certaines approches communes ne fonctionnent pas dans tous les cas:

sys.argv [0]

cela signifie 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, et cela peut arriver dans la vie réelle.

__fichier__

cela signifie utiliser path = os.path.abspath(os.path.dirname(__file__)) , mais j'ai trouvé que cela ne fonctionne pas:

  • py2exe n'a pas d'attribut __file__ , mais il y a un workaround
  • quand vous fuyez le ralenti avec execute() il n'y a pas __file__ attribut
  • OS X 10.6 où j'obtiens NameError: global name '__file__' is not defined

questions connexes avec réponses incomplètes:

  • Python - Trouver le Chemin du Fichier en Cours d'Exécution
  • le chemin vers le fichier courant dépend de la façon dont j'exécute le programme
  • Comment connaître le chemin d'accès de l'exécution d'un script en Python?
  • Changer de répertoire pour le répertoire d'un script Python

je suis à la recherche pour une solution générique , une qui fonctionnerait dans tous les cas d'utilisation ci-dessus.

mise à Jour

voici le résultat d'un test case:

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. 1519640920"
#! /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
165
demandé sur Edward 2010-04-13 22:37:45

10 réponses

vous ne pouvez pas déterminer directement l'emplacement du script principal exécuté. Après tout, parfois le script ne venait pas du tout d'un fichier. Par exemple, il peut 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, puisque les modules sont toujours chargés à partir d'un fichier. Si vous créez un module avec le code suivant et le mettez dans le même répertoire que votre principal script, puis le script principal peut importer le module et l'utiliser pour localiser lui-même.

some_path/module_locator.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))

some_path/main.py:

import module_locator
my_path = module_locator.module_path()

si vous avez plusieurs scripts principaux dans différents répertoires, vous pouvez avoir besoin de plus d'une copie 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 qui sont co-situés avec ton scénario, alors tu n'as pas de chance. Dans de tels cas, l'information que vous recherchez n'existe tout simplement nulle part dans votre programme. Votre meilleur pari serait de fichier d'un bug avec les auteurs de l'outil.

77
répondu Daniel Stutzbach 2010-04-16 14:23:26

D'abord, vous devez importer de inspect et os

from inspect import getsourcefile
from os.path import abspath

ensuite, où que vous vouliez trouver le fichier source à partir de vous, utilisez

abspath(getsourcefile(lambda:0))
47
répondu ArtOfWarfare 2015-11-05 15:20:19

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

il fonctionne pour les scripts réguliers et In idle. Tout ce que je peux dire, c'est de l'essayer pour les autres!

mon usage 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
répondu Garrett Berg 2016-10-16 09:07:48

la réponse courte est que il n'y a pas de façon garantie d'obtenir l'information que vous voulez , cependant il ya des heuristiques qui fonctionnent presque toujours dans la pratique. Vous pouvez regarder Comment trouver l'emplacement de l'exécutable en C? . Il discute du problème d'un point de vue C, mais les solutions proposées sont facilement transcrites en Python.

6
répondu Dale Hagglund 2017-05-23 12:18:20

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))
4
répondu José Crespo Barrios 2017-06-16 14:54:20

voir ma réponse à la question importation de modules à partir du dossier parent pour des informations connexes, y compris pourquoi ma réponse n'utilise pas la variable __file__ non fiable. 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 pièces de la inspecter et os modules.

from inspect import getsourcefile
from os.path import abspath

ensuite, utilisez la ligne suivante partout où vous en avez besoin dans votre code Python:

abspath(getsourcefile(lambda:0))

Comment cela fonctionne:

du module intégré os (description ci-dessous), l'outil abspath est importé.

Routines OS

pour Mac, NT, ou Posix selon le système sur lequel nous sommes.

alors getsourcefile (description ci-dessous) est importé du module intégré inspect .

obtenez des informations utiles à partir d'objets Python vivants.

  • abspath(path) retourne la version complète/absolue d'un chemin de fichier
  • getsourcefile(lambda:0) obtient d'une manière ou d'une autre le fichier source interne de l'objet de la fonction lambda, retourne donc '<pyshell#nn>' dans le shell Python ou renvoie le chemin du fichier de la Code Python en cours d'exécution.

en utilisant abspath sur le résultat de getsourcefile(lambda:0) devrait s'assurer que le chemin de fichier généré est le chemin de fichier complet du fichier Python.

Cette solution expliquée était à l'origine basée sur le code de la réponse à Comment puis-je obtenir le chemin du fichier courant exécuté en Python? .

3
répondu Edward 2017-08-29 13:23:51

cela devrait faire l'affaire de manière transversale (tant que vous n'utilisez pas l'interpréteur ou quelque chose du genre):

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 cherche des modules à utiliser par ce script). Nous pouvons prendre le nom du fichier lui-même, à la fin de sys.argv[0] (qui est ce que j'ai fait avec os.path.basename ). os.path.join les rassemble de façon transversale. os.path.realpath s'assure juste si nous recevons des liens symboliques avec des noms différents que le script lui-même que nous pouvons toujours obtenir le vrai nom du script.

Je n'ai pas de Mac; donc, je n'ai pas testé cela sur un seul. S'il vous plaît laissez-moi savoir si cela fonctionne, il semble qu'il devrait. J'ai testé cela sous Linux (Xubuntu) avec Python 3.4. Notez que de nombreuses solutions pour ce problème ne fonctionnent pas sur Macs (puisque j'ai entendu dire que __file__ n'est pas présent sur Macs).

Notez que si votre script est symbolique link, il vous donnera le chemin du fichier auquel il renvoie (et non le chemin du lien symbolique).

2
répondu Shule 2014-09-10 22:04:33

vous pouvez utiliser Path à partir du pathlib module:

from pathlib import Path

# ...

Path(__file__)

Vous pouvez utiliser l'appel à parent pour aller plus loin dans le chemin:

Path(__file__).parent
2
répondu Gavriel Cohen 2016-10-10 09:49:04

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.

1
répondu dgbcgx 2018-04-04 15:19:09

il suffit D'ajouter 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
répondu H. Kamran 2017-11-15 13:40:51