Comment puis-je obtenir le chemin et le nom du fichier en cours d’exécution ?

StackOverflow https://stackoverflow.com/questions/50499

  •  09-06-2019
  •  | 
  •  

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 appels script_2.py.
  • À son tour, script_2.py appels script_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.)

Était-ce utile?

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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top