Question Récupération du chemin du module python


Je veux détecter si le module a changé. Maintenant, en utilisant inotify est simple, vous avez juste besoin de connaître le répertoire dont vous voulez recevoir les notifications.

Comment puis-je récupérer le chemin d'un module en python?


526
2017-10-29 17:52


origine


Réponses:


import a_module
print a_module.__file__

Vous donnera en fait le chemin vers le fichier .pyc qui a été chargé, au moins sur Mac OS X. Donc je suppose que vous pouvez le faire

import os
path = os.path.dirname(amodule.__file__)

Vous pouvez aussi essayer

path = os.path.abspath(amodule.__file__)

Pour obtenir le répertoire pour rechercher des modifications.


615
2017-10-29 23:57



Il y a inspect module en python.

Documentation officielle

Le module d'inspection fournit plusieurs fonctions utiles pour aider à   des informations sur les objets vivants tels que les modules, les classes, les méthodes,   fonctions, les retraçages, les objets d'image et les objets de code. Par exemple,   il peut vous aider à examiner le contenu d'une classe, récupérer la source   code d'une méthode, extraire et formater la liste d'arguments pour une fonction,   ou obtenez toutes les informations dont vous avez besoin pour afficher un retraçage détaillé.

Exemple:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'

190
2017-08-28 07:24



Comme l'ont dit les autres réponses, la meilleure façon de le faire est de __file__ (démontré à nouveau ci-dessous). Cependant, il y a une mise en garde importante, qui est que __file__ n'existe pas si vous exécutez le module seul (c'est-à-dire __main__).

Par exemple, disons que vous avez deux fichiers (les deux sont sur votre PYTHONPATH):

#/path1/foo.py
import bar
print(bar.__file__)

et

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

L'exécution de foo.py donnera la sortie:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

TOUTEFOIS, si vous essayez d'exécuter bar.py seul, vous obtiendrez:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

J'espère que cela t'aides. Cette mise en garde m'a coûté beaucoup de temps et de confusion en testant les autres solutions présentées.


57
2018-06-20 19:05



Je vais essayer d'aborder quelques variantes de cette question:

  1. trouver le chemin du script appelé
  2. trouver le chemin du script en cours d'exécution
  3. trouver le répertoire du script appelé

(Certaines de ces questions ont été posées sur SO, mais ont été fermées en double et redirigées ici.)

Mises en garde de l'utilisation __file__

Pour un module que vous avez importé:

import something
something.__file__ 

retournera le absolu chemin du module. Cependant, étant donné le script suivant foo.py:

#foo.py
print '__file__', __file__

L'appeler avec 'python foo.py' retournera simplement 'foo.py'. Si vous ajoutez un shebang:

#!/usr/bin/python 
#foo.py
print '__file__', __file__

et appelez-le en utilisant ./foo.py, il renverra './foo.py'. Appel à partir d'un répertoire différent, (par exemple mettre foo.py dans la barre de répertoire), puis en appelant soit

python bar/foo.py

ou en ajoutant un shebang et en exécutant le fichier directement:

bar/foo.py

retournera 'bar / foo.py' (le relatif chemin).

Trouver le répertoire

Maintenant, à partir de là pour obtenir le répertoire, os.path.dirname(__file__) peut aussi être difficile. Au moins sur mon système, il renvoie une chaîne vide si vous l'appelez du même répertoire que le fichier. ex.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

va sortir:

__file__ is: foo.py
os.path.dirname(__file__) is: 

En d'autres termes, il renvoie une chaîne vide, donc cela ne semble pas fiable si vous voulez l'utiliser pour le courant fichier (par opposition à fichier d'un module importé). Pour contourner cela, vous pouvez l'enrouler dans un appel à abspath:

# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))

qui produit quelque chose comme:

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Notez que abspath () ne résout PAS les liens symboliques. Si vous voulez faire cela, utilisez plutôt realpath (). Par exemple, en créant un lien symbolique file_import_testing_link pointant vers file_import_testing.py, avec le contenu suivant:

import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)

L'exécution imprimera des chemins absolus quelque chose comme:

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link -> file_import_testing.py

Utiliser inspecter

@SummerBreeze mentionne l'utilisation du inspecter module.

Cela semble bien fonctionner, et est assez concis, pour les modules importés:

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

retourne docilement le chemin absolu. Cependant, pour trouver le chemin du script en cours d'exécution, je n'ai pas vu de moyen de l'utiliser.


30
2018-05-30 02:15



Je ne comprends pas pourquoi personne n'en parle, mais pour moi, la solution la plus simple consiste à utiliser imp.find_module ("modulename") (Documentation ici):

import imp
imp.find_module("os")

Il donne un tuple avec le chemin en deuxième position:

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

L'avantage de cette méthode par rapport à l'inspection est que vous n'avez pas besoin d'importer le module pour le faire fonctionner et que vous pouvez utiliser une chaîne en entrée. Utile lors de la vérification de modules appelés dans un autre script par exemple.

MODIFIER:

En python3, importlib le module devrait faire:

Doc de importlib.util.find_spec:

Renvoie la spécification pour le module spécifié.

D'abord, sys.modules est vérifié pour voir si le module a déjà été importé. Si c'est le cas, alors sys.modules [nom].spec est retourné. Si cela arrive à être   défini sur None, ValueError est déclenché. Si le module n'est pas dans   sys.modules, puis sys.meta_path est recherché pour une spécification appropriée avec le   valeur du 'chemin' donné aux trouveurs. Aucun n'est retourné si aucune spécification ne pouvait   être trouvé.

Si le nom est pour submodule (contient un point), le module parent est   automatiquement importé.

Les arguments name et package fonctionnent de la même façon que importlib.import_module ().   En d'autres termes, les noms relatifs des modules (avec les points principaux) fonctionnent.


18
2018-03-11 00:10



C'était trivial.

Chaque module a un __file__ variable qui montre son chemin relatif d'où vous êtes en ce moment.

Par conséquent, obtenir un répertoire pour le module pour le notifier est simple comme:

os.path.dirname(__file__)

16
2017-10-29 19:18



import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)

14
2017-12-13 17:35



J'ai donc passé pas mal de temps à essayer de faire ça avec py2exe Le problème était d'obtenir le dossier de base du script, qu'il soit exécuté en tant que script python ou en tant qu'exécutable py2exe. De plus, le faire fonctionner à partir du dossier actuel, d'un autre dossier ou (c'était le plus difficile) depuis le chemin du système.

Finalement, j'ai utilisé cette approche, en utilisant sys.frozen comme un indicateur de fonctionnement dans py2exe:

import os,sys
if hasattr(sys,'frozen'): # only when running in py2exe this exists
    base = sys.prefix
else: # otherwise this is a regular python script
    base = os.path.dirname(os.path.realpath(__file__))

6
2018-03-18 16:28



Utilitaire de ligne de commande

Vous pouvez le modifier en un utilitaire de ligne de commande,

python-which <package name>

enter image description here


Créer /usr/local/bin/python-which

#!/usr/bin/env python

import importlib
import os
import sys

args = sys.argv[1:]
if len(args) > 0:
    module = importlib.import_module(args[0])
    print os.path.dirname(module.__file__)

Rendez-le exécutable

sudo chmod +x /usr/local/bin/python-which

4
2017-08-15 16:27



import module
print module.__path__

Les packages prennent en charge un attribut spécial supplémentaire __path__. C'est   initialisé pour être une liste contenant le nom du répertoire   le paquet __init__.py avant que le code dans ce fichier soit exécuté.   Cette variable peut être modifiée. Cela affecte les recherches futures   modules et sous-packages contenus dans le package.

Bien que cette fonctionnalité ne soit pas souvent nécessaire, elle peut être utilisée pour étendre   ensemble de modules trouvés dans un paquet.

La source


4
2017-08-16 23:04



Si la seule mise en garde de l'utilisation __file__ est le moment où le répertoire relatif est vide (c’est-à-dire que lorsqu’il est exécuté en tant que script à partir du même répertoire que le script), une solution triviale est:

import os.path
mydir = os.path.dirname(__file__) or '.'
full  = os.path.abspath(mydir)
print __file__, mydir, full

Et le résultat:

$ python teste.py 
teste.py . /home/user/work/teste

L'astuce est dans or '.' après le dirname() appel. Il définit le répertoire comme ., ce qui signifie répertoire actuel et est un répertoire valide pour toute fonction liée au chemin.

Ainsi, en utilisant abspath() n'est pas vraiment nécessaire. Mais si vous l'utilisez quand même, le tour n'est pas nécessaire: abspath() accepte les chemins vides et les interprète correctement comme le répertoire en cours.


2
2017-08-15 01:22