J'avais l'habitude d'ouvrir des fichiers qui se trouvaient dans le même répertoire que le script Python en cours d'exécution en utilisant simplement une commande comme
open("Some file.txt", "r")
Cependant, j'ai découvert que lorsque le script était exécuté sous Windows en double-cliquant dessus, il tentait d'ouvrir le fichier à partir du mauvais répertoire.
Depuis, j'ai utilisé une commande du formulaire
open(os.path.join(sys.path[0], "Some file.txt"), "r")
chaque fois que je voulais ouvrir un fichier. Cela fonctionne pour mon utilisation particulière, mais je ne sais pas si cela sys.path[0]
pourrait échouer dans un autre cas d'utilisation.
Ma question est donc la suivante: quel est le moyen le meilleur et le plus fiable d'ouvrir un fichier qui se trouve dans le même répertoire que le script Python en cours d'exécution?
Voici ce que j'ai pu comprendre jusqu'à présent:
os.getcwd()
etos.path.abspath('')
renvoie le "répertoire de travail actuel", pas le répertoire de script.os.path.dirname(sys.argv[0])
etos.path.dirname(__file__)
renvoyer le chemin utilisé pour appeler le script, qui peut être relatif ou même vide (si le script est dans le cwd). De plus,__file__
n'existe pas lorsque le script est exécuté en IDLE ou PythonWin.sys.path[0]
etos.path.abspath(os.path.dirname(sys.argv[0]))
semblent renvoyer le répertoire de script. Je ne sais pas s'il y a une différence entre ces deux.
Éditer:
Je viens de réaliser que ce que je veux faire serait mieux décrit comme "ouvrir un fichier dans le même répertoire que le module contenant". En d'autres termes, si j'importe un module que j'ai écrit dans un autre répertoire, et que ce module ouvre un fichier, je veux qu'il recherche le fichier dans le répertoire du module. Je ne pense pas que ce que j'ai trouvé soit capable de faire ça ...
__file__
ne peut pas être utilisé, utilisez à lasys.argv[0]
place dedirname(__file__)
. Le reste devrait fonctionner comme prévu. J'aime utiliser__file__
parce que dans le code de la bibliothèque, il sesys.argv[0]
peut que le code ne pointe pas du tout vers votre code, surtout s'il est importé via un script tiers.realpath( join( getcwd(), dirname(__file__) ))
comme décrit ici?Pour citer la documentation Python:
sys.path [0] est ce que vous recherchez.
la source
os.path.join(sys.path[0], 'some file.txt')
. Cela devrait gérer correctement les espaces et les barres obliques sur tous les systèmes.Ok voici ce que je fais
sys.argv est toujours ce que vous tapez dans le terminal ou utilisez comme chemin de fichier lors de son exécution avec python.exe ou pythonw.exe
Par exemple, vous pouvez exécuter le fichier text.py de plusieurs façons, elles vous donnent chacune une réponse différente, elles vous donnent toujours le chemin d'accès que python a été tapé.
Ok, sachez que vous pouvez obtenir le nom du fichier, très bien, maintenant pour obtenir le répertoire de l'application, vous pouvez utiliser os.path, en particulier abspath et dirname
Cela produira ceci:
il affichera toujours ceci, peu importe si vous tapez python test.py ou python "C: \ Documents and Settings \ Admin \ test.py"
Le problème avec l'utilisation de __file__ Considérez ces deux fichiers test.py
import_test.py
Sortie de "python test.py"
Sortie de "python test_import.py"
Ainsi, comme vous pouvez le voir, file vous donne toujours le fichier python à partir duquel il est exécuté, alors que sys.argv [0] vous donne toujours le fichier que vous avez exécuté depuis l'interpréteur. En fonction de vos besoins, vous devrez choisir celui qui correspond le mieux à vos besoins.
la source
__file__
est censé "toujours vous donner le chemin vers le fichier courant", etsys.argv[0]
est censé "toujours donner le chemin du script qui a initié le processus". Dans tous les cas, l'utilisation__file__
dans le script qui est appelé vous donne toujours des résultats précis.__file__
au niveau supérieur du script, cela fonctionnera comme prévu.J'ai pu utiliser le code fourni par dcolish avec succès car j'avais un problème similaire avec la lecture d'un fichier texte spécifique. Le fichier n'est pas dans le même cwd que le fichier Python.
la source
Je le ferais de cette façon:
Le code ci-dessus construit un chemin absolu vers le fichier en utilisant abspath et équivaut à utiliser
normpath(join(os.getcwd(), path))
[qui provient des pydocs]. Il vérifie ensuite si ce fichier existe réellement , puis utilise un gestionnaire de contexte pour l'ouvrir afin que vous n'ayez pas à vous rappeler d'appeler close sur le descripteur de fichier. IMHO, le faire de cette façon vous évitera beaucoup de douleur à long terme.la source
os.path.abspath
ne résout pas les chemins d'accès aux fichiers dans le même dossier que le script si le script n'est pas dans le répertoire actuel.