Comment puis-je obtenir le chemin et le nom du fichier en cours d’exécution ?
Question
J'ai des scripts appelant d'autres fichiers de script, mais j'ai besoin d'obtenir le chemin du fichier en cours d'exécution dans le processus.
Par exemple, disons que j'ai trois fichiers.En utilisant fichier exécutable:
script_1.py
appelsscript_2.py
.- À son tour,
script_2.py
appelsscript_3.py
.
Comment puis-je obtenir le nom du fichier et le chemin de script_3.py
, du code à l'intérieur script_3.py
, sans avoir à transmettre ces informations sous forme d'arguments depuis script_2.py
?
(Exécution os.getcwd()
renvoie le chemin du fichier du script de démarrage d'origine et non celui du fichier actuel.)
La solution
p1.py :
execfile("p2.py")
p2.py :
import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory
Autres conseils
__file__
comme d'autres l'ont dit.Vous souhaiterez peut-être également utiliser os.path.realpath pour éliminer les liens symboliques :
import os
os.path.realpath(__file__)
Mise à jour 2018-11-28 :
Voici un résumé des expériences avec Python 2 et 3.Avec
main.py - exécute foo.py
foo.py - exécute lib/bar.py
lib/bar.py - imprime les expressions de chemin de fichier
| Python | Run statement | Filepath expression |
|--------+---------------------+----------------------------------------|
| 2 | execfile | os.path.abspath(inspect.stack()[0][1]) |
| 2 | from lib import bar | __file__ |
| 3 | exec | (wasn't able to obtain it) |
| 3 | import lib.bar | __file__ |
Pour Python 2, il pourrait être plus clair de passer aux packages afin de pouvoir utiliser from lib import bar
- il suffit d'ajouter du vide __init__.py
fichiers dans les deux dossiers.
Pour Python 3, execfile
n'existe pas - l'alternative la plus proche est exec(open(<filename>).read())
, bien que cela affecte les cadres de pile.Le plus simple est d'utiliser import foo
et import lib.bar
- Non __init__.py
fichiers nécessaires.
Voir également Différence entre l'importation et le fichier exécutable
Réponse originale :
Voici une expérience basée sur les réponses de ce fil de discussion - avec Python 2.7.10 sous Windows.
Ceux basés sur la pile sont les seuls qui semblent donner des résultats fiables.Les deux derniers ont la syntaxe la plus courte, c'est à dire.-
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
Voici à ceux-ci ajoutés à système comme fonctions !Crédit à @Usagi et @pablog
Basé sur les trois fichiers suivants et en exécutant main.py à partir de son dossier avec python main.py
(également essayé des fichiers exécutables avec des chemins absolus et des appels à partir d'un dossier séparé).
C:\chemins de fichiers\main.py : execfile('foo.py')
C:\chemins de fichiers\foo.py : execfile('lib/bar.py')
C:\filepaths\lib\bar.py :
import sys
import os
import inspect
print "Python " + sys.version
print
print __file__ # main.py
print sys.argv[0] # main.py
print inspect.stack()[0][1] # lib/bar.py
print sys.path[0] # C:\filepaths
print
print os.path.realpath(__file__) # C:\filepaths\main.py
print os.path.abspath(__file__) # C:\filepaths\main.py
print os.path.basename(__file__) # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print
print sys.path[0] # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:\filepaths
print os.path.dirname(os.path.abspath(__file__)) # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0])) # C:\filepaths
print os.path.dirname(__file__) # (empty string)
print
print inspect.getfile(inspect.currentframe()) # lib/bar.py
print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
print
Je pense que c'est plus propre :
import inspect
print inspect.stack()[0][1]
et obtient les mêmes informations que :
print inspect.getfile(inspect.currentframe())
Où [0] est l'image actuelle dans la pile (en haut de la pile) et [1] est le nom du fichier, augmentez pour reculer dans la pile, c'est-à-dire
print inspect.stack()[1][1]
serait le nom de fichier du script qui a appelé l'image actuelle.De plus, l'utilisation de [-1] vous amènera au bas de la pile, le script appelant d'origine.
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Les suggestions marquées comme les meilleures sont toutes vraies si votre script ne contient qu'un seul fichier.
Si vous souhaitez connaître le nom de l'exécutable (c'est-à-direle fichier racine transmis à l'interpréteur python pour le programme en cours) à partir d'un fichier pouvant être importé en tant que module, vous devez le faire (supposons que ce soit dans un fichier nommé foo.py):
import inspect
print inspect.stack()[-1][1]
Parce que la dernière chose ([-1]
) sur la pile est la première chose qui y est entrée (les piles sont des structures de données LIFO/FILO).
Puis dans le fichier bar.py si tu import foo
ça va imprimer bar.py, plutôt que foo.py, quelle serait la valeur de tous ces éléments :
__file__
inspect.getfile(inspect.currentframe())
inspect.stack()[0][1]
import os
print os.path.basename(__file__)
cela nous donnera uniquement le nom du fichier.c'est à dire.si le chemin absolu du fichier est c:\abcd\abc.py alors la 2ème ligne imprimera abc.py
Ce que vous entendez par "le chemin du fichier en cours d'exécution dans le processus" n'est pas tout à fait clair.sys.argv[0]
contient généralement l'emplacement du script invoqué par l'interpréteur Python.Vérifier la documentation système pour plus de détails.
Comme @Tim et @Pat Notz l'ont souligné, l'attribut __file__ donne accès à
le fichier à partir duquel le module a été chargé, s'il était chargé à partir d'un fichier
J'ai un script qui doit fonctionner sous environnement Windows.Ce code extrait est ce avec quoi j'ai terminé :
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
c'est une décision assez délicate.Mais cela ne nécessite aucune bibliothèque externe et c'est la chose la plus importante dans mon cas.
import os
os.path.dirname(os.path.abspath(__file__))
Pas besoin d'inspecter ou de toute autre bibliothèque.
Cela a fonctionné pour moi lorsque j'ai dû importer un script (à partir d'un répertoire différent de celui du script exécuté), qui utilisait un fichier de configuration résidant dans le même dossier que le script importé.
Le __file__
L'attribut fonctionne à la fois pour le fichier contenant le code d'exécution principal ainsi que pour les modules importés.
Voir https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
import sys
print sys.path[0]
cela imprimerait le chemin du script en cours d'exécution
Je pense que c'est juste __file__
On dirait que vous voudrez peut-être aussi consulter le inspecter le module.
Vous pouvez utiliser inspect.stack()
import inspect,os
inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'
Essaye ça,
import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]
Cela devrait fonctionner :
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Pour obtenir le répertoire du script en cours d'exécution
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Pour conserver la cohérence de la migration sur toutes les plateformes (macOS/Windows/Linux), essayez :
path = r'%s' % os.getcwd().replace('\\','/')
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
J'ai utilisé l'approche avec __file__
os.path.abspath(__file__)
Mais il y a une petite astuce, il renvoie le fichier .py lorsque le code est exécuté la première fois, les exécutions suivantes donnent le nom du fichier * .pyc
donc je suis resté avec :
inspect.getfile(inspect.currentframe())
ou
sys._getframe().f_code.co_filename
J'ai écrit une fonction qui prend en compte Eclipse débogueur et Test de l'unité.Il renvoie le dossier du premier script que vous lancez.Vous pouvez éventuellement spécifier le __déposer__ var, mais l'essentiel est que vous n'ayez pas à partager cette variable entre tous vos hiérarchie d'appel.
Peut-être que vous pouvez gérer d'autres cas particuliers que je n'ai pas vus, mais pour moi, ça va.
import inspect, os
def getRootDirectory(_file_=None):
"""
Get the directory of the root execution file
Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
For eclipse user with unittest or debugger, the function search for the correct folder in the stack
You can pass __file__ (with 4 underscores) if you want the caller directory
"""
# If we don't have the __file__ :
if _file_ is None:
# We get the last :
rootFile = inspect.stack()[-1][1]
folder = os.path.abspath(rootFile)
# If we use unittest :
if ("/pysrc" in folder) & ("org.python.pydev" in folder):
previous = None
# We search from left to right the case.py :
for el in inspect.stack():
currentFile = os.path.abspath(el[1])
if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
break
previous = currentFile
folder = previous
# We return the folder :
return os.path.dirname(folder)
else:
# We return the folder according to specified __file__ :
return os.path.dirname(os.path.realpath(_file_))
Le moyen le plus simple est :
dans script_1.py :
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
dans script_2.py :
sys.argv[0]
P.S. :J'ai essayé execfile
, mais comme il lit script_2.py comme une chaîne, sys.argv[0]
revenu <string>
.
J'ai toujours simplement utilisé la fonctionnalité OS de Current Working Directory, ou CWD.Cela fait partie de la bibliothèque standard et est très simple à mettre en œuvre.Voici un exemple:
import os
base_directory = os.getcwd()
La plupart de ces réponses ont été écrites en Python version 2.x ou antérieure.Dans Python 3.x, la syntaxe de la fonction d'impression a changé pour exiger des parenthèses, c'est-à-direimprimer().
Ainsi, cette réponse précédente avec un score élevé de l'utilisateur 13993 dans Python 2.x :
import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory
Devient en Python 3.x :
import inspect, os
print(inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory
si vous voulez juste le nom du fichier sans ./
ou .py
tu peux essayer ça
filename = testscript.py
file_name = __file__[2:-3]
file_name
Imprimera TestScript que vous pouvez générer ce que vous voulez en modifiant l'index à l'intérieur [
import os
import wx
# return the full path of this file
print(os.getcwd())
icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)
# put the icon on the frame
self.SetIcon(icon)