264 votes

Comment ouvrir de manière fiable un fichier dans le même répertoire qu'un script Python

J'ai utilisé pour ouvrir les fichiers qui étaient dans le même répertoire que le cours d'exécution d'un script Python en utilisant simplement une commande comme celle - open("Some file.txt", "r"). Cependant, j'ai découvert que lorsque le script a été exécuté sous Windows en double-cliquant dessus, qu'il allait essayer d'ouvrir le fichier à partir du répertoire incorrect.

Depuis lors, j'ai utilisé une commande de la forme
open(os.path.join(sys.path[0], "Some file.txt"), "r")
chaque fois que je voulais ouvrir un fichier. Cela fonctionne pour mon usage particulier, mais je ne suis pas sûr si sys.path[0] peut échouer dans certains autres cas d'utilisation. Donc ma question est: Quelle est la meilleure et la plus fiable pour ouvrir un fichier dans le même répertoire que le cours d'exécution d'un script Python?

Voici ce que j'ai pu découvrir jusqu'à présent:

  • os.getcwd() et os.path.abspath('') retour le "répertoire de travail", et non pas le répertoire de script.

  • os.path.dirname(sys.argv[0]) et os.path.dirname(__file__) retour le chemin d'accès utilisé pour appeler le script, ce qui peut être relatif ou même vide (si le script est dans le cwd). Aussi, __file__ n'existe pas lorsque le script est exécuté au RALENTI ou PythonWin.

  • sys.path[0] et os.path.abspath(os.path.dirname(sys.argv[0])) semblent revenir le répertoire de script. Je ne suis pas sûr si il n'y a aucune différence entre ces deux.

[edit:]

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 celui contenant le module". En d'autres termes, si je importer un module que j'ai écrit dans un autre répertoire, et que le module s'ouvre un fichier, je le veux chercher le fichier dans le répertoire du module. Je ne pense pas que tout ce que j'ai trouvé est en mesure de le faire...

305voto

André Caron Points 19543

J'ai toujours utiliser:

__location__ = os.path.realpath(
    os.path.join(os.getcwd(), os.path.dirname(__file__)))

L' join() appel ajoute le répertoire de travail courant, mais la documentation dit que si le chemin est absolu, toutes les autres voies de gauche sont abandonnées. Par conséquent, getcwd() est supprimée lorsque dirname(__file__) renvoie un chemin d'accès absolu.

Aussi, l' realpath appel résout les liens symboliques s'il en existe. Cela évite les problèmes lors du déploiement avec setuptools sur les systèmes Linux (les scripts sont liés à d' /usr/bin/ - au moins sur Debian).

Vous pouvez utiliser les méthodes suivantes pour ouvrir les fichiers dans le même dossier:

f = open(os.path.join(__location__, 'bundled-resource.jpg'));
# ...

Je l'utilise pour le bundle de ressources avec plusieurs application Django à la fois sur Windows et Linux et il fonctionne comme un charme!

52voto

RED MONKEY Points 175

Pour citer un extrait de la documentation Python:

Comme initialisé au démarrage du programme, le premier élément de cette liste, chemin[0], est le répertoire contenant le script qui a été utilisé pour invoquer l'interpréteur Python. Si le script d'annuaire n'est pas disponible (par exemple, si l'interprète est appelé de manière interactive ou si le script est lu à partir de l'entrée standard), chemin[0] est la chaîne vide, qui dirige Python pour les modules de recherche dans le répertoire courant de la première. Notez que le répertoire de script est inséré avant les entrées inséré à la suite de PYTHONPATH.

sys.chemin[0] est-ce que vous cherchez.

21voto

Zimm3r Points 901

Ok, voici ce que je fais

sys.argv est toujours ce que vous tapez dans le terminal ou l'utiliser comme le chemin d'accès au fichier lors de l'exécution avec python.exe ou pythonw.exe

Par exemple, vous pouvez exécuter le fichier text.py de plusieurs façons, ils vous donnent une réponse différente, ils vous donnent toujours le chemin que python a été tapé.

    C:\Documents and Settings\Admin>python test.py
    sys.argv[0]: test.py
    C:\Documents and Settings\Admin>python "C:\Documents and Settings\Admin\test.py"
    sys.argv[0]: C:\Documents and Settings\Admin\test.py

Ok donc je sais que vous pouvez obtenir le nom de fichier, la grande affaire, maintenant pour obtenir le répertoire de l'application, vous pouvez savoir utiliser os.chemin, plus précisément abspath et dirname

    import sys, os
    print os.path.dirname(os.path.abspath(sys.argv[0]))

Qui sera de sortie ce:

   C:\Documents and Settings\Admin\

il sera toujours sortie ce peu importe si vous tapez python test.py ou python "C:\Documents et Settings\Admin\test.py"

Le problème avec l'aide d' _fichier_ Tenir compte de ces deux fichiers test.py

import sys
import os

def paths():
        print "__file__: %s" % __file__
        print "sys.argv: %s" % sys.argv[0]

        a_f = os.path.abspath(__file__)
        a_s = os.path.abspath(sys.argv[0])

        print "abs __file__: %s" % a_f
        print "abs sys.argv: %s" % a_s

if __name__ == "__main__":
    paths()

import_test.py

import test
import sys

test.paths()

print "--------"
print __file__
print sys.argv[0]

La sortie de "python test.py"

C:\Documents and Settings\David>python test.py
__file__: test.py
sys.argv: test.py
abs __file__: C:\Documents and Settings\David\test.py
abs sys.argv: C:\Documents and Settings\David\test.py

La sortie de "python test_import.py"

C:\Documents and Settings\David>python test_import.py
__file__: C:\Documents and Settings\David\test.pyc
sys.argv: test_import.py
abs __file__: C:\Documents and Settings\David\test.pyc
abs sys.argv: C:\Documents and Settings\David\test_import.py
--------
test_import.py
test_import.py

Donc, comme vous pouvez le voir fichier vous donne toujours le fichier python il est exécuté à partir d', où en tant que sys.argv[0] vous donne le fichier que vous avez exécuté à partir de l'interprète toujours. Selon vos besoins, vous aurez besoin de choisir celui qui correspond le mieux à vos besoins.

-2voto

dcolish Points 3814

J'aimerais faire de cette façon:

from os.path import abspath, exists

f_path = abspath("fooabar.txt")

if exists(f_path):
    with open(f_path) as f:
        print f.read()

Le code ci-dessus crée un chemin absolu vers le fichier à l'aide de abspath et est équivalent à l'utilisation de normpath(join(os.getcwd(), path)) [c'est à partir de la pydocs]. Ensuite, il vérifie si le fichier existe et ensuite utilise un gestionnaire de contexte pour l'ouvrir de sorte que vous n'avez pas à penser à appeler close sur le descripteur de fichier. À mon humble avis, cette façon de faire vous permettra d'économiser beaucoup de douleur dans le long terme.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X