Question

Je veux détecter si le module a changé. Maintenant, utiliser inotify est simple, il vous suffit de connaître le répertoire dans lequel vous souhaitez recevoir les notifications.

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

Était-ce utile?

La solution

import a_module
print(a_module.__file__)

Vous indiquera en fait le chemin d'accès au fichier .pyc chargé, du moins sous Mac OS X. Vous avez donc la possibilité de le faire:

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

Vous pouvez également essayer:

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

Pour obtenir le répertoire du module.

Autres conseils

Il existe un module inspect en python.

Documentation officielle

  

Le module inspecter fournit plusieurs fonctions utiles pour vous aider à obtenir   informations sur les objets en direct tels que modules, classes, méthodes,   fonctions, traces de retour, objets cadre et objets code. Par exemple,   cela peut vous aider à examiner le contenu d'une classe, récupérer le source   code d'une méthode, extraire et formater la liste d'arguments d'une fonction,   ou obtenez toutes les informations nécessaires pour afficher une trace détaillée.

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'

Comme l’ont dit d’autres réponses, la meilleure façon de procéder consiste à utiliser __ fichier __ (à nouveau démontré ci-dessous). Cependant, il y a une mise en garde importante, à savoir que le __ fichier __ n'existe PAS si vous exécutez le module seul (c'est-à-dire en tant que __ principal __ ).

Par exemple, supposons que vous ayez deux fichiers (qui se trouvent tous les deux sur votre PYTHONPATH):

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

et

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

Lancer foo.py donnera le résultat:

/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

TOUJOURS 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 ça aide. Cette mise en garde m'a coûté beaucoup de temps et de confusion en testant les autres solutions présentées.

Je vais également essayer de traiter quelques variations sur cette question:

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

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

Mises en garde concernant l'utilisation de __ fichier __

Pour un module que vous avez importé:

import something
something.__file__ 

renverra le chemin absolu 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 avec ./foo.py, il retournera "./foo.py". L'appeler depuis un répertoire différent (par exemple, mettre foo.py dans la barre de répertoires), puis en appelant

python bar/foo.py

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

bar/foo.py

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

Recherche du répertoire

À partir de là, pour obtenir le répertoire, os.path.dirname (__ fichier __) peut également être délicat. Au moins sur mon système, il renvoie une chaîne vide si vous l'appelez à partir 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__)

affichera:

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

En d'autres termes, il renvoie une chaîne vide. Cela ne semble donc pas fiable si vous souhaitez l'utiliser pour le fichier actuel (par opposition au fichier de un module importé). Pour résoudre ce problème, vous pouvez l'envelopper 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 génère 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 realpath () à la place. Par exemple, créer un lien symbolique file_import_testing_link pointant sur 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 du type:

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

file_import_testing_link - > fichier_import_test.py

Utilisation de inspect

@SummerBreeze mentionne l'utilisation du module inspect .

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)

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

Je ne comprends pas pourquoi personne ne parle de cela, mais pour moi la solution la plus simple consiste à imp.find_module ("modulename") (documentation here ):

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 à la commande "inspecter". le premier est que vous n'avez pas besoin d'importer le module pour le faire fonctionner, et 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 :

Dans python3, le module importlib devrait faire:

Doc de importlib.util.find_spec :

  

Renvoie la spécification du module spécifié.

     

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

     

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

     

Les arguments name et package fonctionnent de la même manière que importlib.import_module ().   En d’autres termes, les noms de modules relatifs (avec les points principaux) fonctionnent.

C'était trivial.

Chaque module a une variable __ fichier __ qui indique son chemin relatif depuis l'endroit où vous vous trouvez actuellement.

Par conséquent, obtenir un répertoire pour que le module le notifie est simple:

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

Utilitaire de ligne de commande

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

python-which <package name>

 entrez la description de l'image ici

Créez / usr / local / bin / python-quel

#!/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

J'ai donc passé pas mal de temps à essayer de le faire 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. Pour que cela fonctionne également, qu'il soit exécuté à partir du dossier actuel, d'un autre dossier ou (c'est le cas le plus difficile) du chemin du système.

Finalement, j'ai utilisé cette approche, en utilisant sys.frozen comme indicateur de l'exécution 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__))
import module
print module.__path__
  

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

     

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

Source

vous pouvez simplement importer votre module puis cliquez sur son nom et vous obtiendrez son chemin d'accès complet

>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>

Si le seul inconvénient lié à l'utilisation de __ fichier __ concerne l'actuel, le répertoire relatif est vide (c'est-à-dire 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

Le truc est dans ou '.' après l'appel dirname () . Il définit le répertoire comme . , ce qui signifie répertoire courant et constitue un répertoire valide pour toute fonction liée au chemin.

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

J'aimerais contribuer avec un scénario commun (en Python 3) et explorer quelques approches pour le résoudre.

La fonction intégrée open () accepte les fichiers relatifs. ou chemin absolu comme premier argument. Le chemin relatif est traité comme par rapport au répertoire de travail actuel . Il est donc recommandé de passer le chemin absolu au fichier.

En termes simples, si vous exécutez un fichier de script avec le code suivant, il n'est pas garanti que le fichier example.txt sera créé dans le même répertoire le fichier de script se trouve:

with open('example.txt', 'w'):
    pass

Pour corriger ce code, nous devons obtenir le chemin du script et le rendre absolu. Pour que le chemin soit absolu, nous utilisons simplement le os Fonction .path.realpath () . Pour obtenir le chemin du script, plusieurs fonctions courantes renvoient différents résultats:

  • os.getcwd ()
  • os.path.realpath ('exemple.txt')
  • sys.argv [0]
  • __ fichier __

Les deux fonctions os.getcwd () et < a href = "https://docs.python.org/3/library/os.path.html#os.path.realpath" rel = "aucune erreur de suivi"> os.path.realpath () chemin de retour résultats basés sur le répertoire de travail actuel . Généralement pas ce que nous voulons. Le premier élément de la liste sys.argv est le < em> chemin du script racine (le script que vous exécutez), que vous appeliez la liste dans le script racine lui-même ou dans l'un de ses modules. Cela peut être utile dans certaines situations. La variable __file__ contient le chemin du module à partir duquel elle a été appelée. .

Le code suivant crée correctement un fichier example.txt dans le même répertoire que le script:

filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')

with open(filepath, 'w'):
    pass

À partir des modules d'un paquet Python, je devais faire référence à un fichier qui se trouvait dans le même répertoire que le paquet. Ex.

some_dir/
  maincli.py
  top_package/
    __init__.py
    level_one_a/
      __init__.py
      my_lib_a.py
      level_two/
        __init__.py
        hello_world.py
    level_one_b/
      __init__.py
      my_lib_b.py

Donc, ci-dessus, j’ai dû appeler maincli.py à partir du module my_lib_a.py, sachant que top_package et maincli.py se trouvent dans le même répertoire. Voici comment obtenir le chemin d'accès à maincli.py:

import sys
import os
import imp


class ConfigurationException(Exception):
    pass


# inside of my_lib_a.py
def get_maincli_path():
    maincli_path = os.path.abspath(imp.find_module('maincli')[1])
    # top_package = __package__.split('.')[0]
    # mod = sys.modules.get(top_package)
    # modfile = mod.__file__
    # pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))
    # maincli_path = os.path.join(pkg_in_dir, 'maincli.py')

    if not os.path.exists(maincli_path):
        err_msg = 'This script expects that "maincli.py" be installed to the '\
        'same directory: "{0}"'.format(maincli_path)
        raise ConfigurationException(err_msg)

    return maincli_path

D'après la publication de PlasmaBinturong, j'ai modifié le code.

Si vous souhaitez effectuer cette opération de manière dynamique dans un "programme" essayez ce code:
Mon problème est que vous ne connaissez peut-être pas le nom exact du module à "code dur". il. Il peut être sélectionné dans une liste ou ne pas être en cours d'exécution pour utiliser __file __.

(Je sais, cela ne fonctionnera pas en Python 3)

global modpath
modname = 'os' #This can be any module name on the fly
#Create a file called "modname.py"
f=open("modname.py","w")
f.write("import "+modname+"\n")
f.write("modpath = "+modname+"\n")
f.close()
#Call the file with execfile()
execfile('modname.py')
print modpath
<module 'os' from 'C:\Python27\lib\os.pyc'>

J'ai essayé de me débarrasser du "global" problème, mais a trouvé des cas où cela n'a pas fonctionné Je pense que "execfile ()" peut être émulé dans Python 3 Etant donné qu’il s’agit d’un programme, il peut facilement être intégré dans une méthode ou un module en vue de sa réutilisation.

Si vous souhaitez connaître le chemin absolu de votre script, vous pouvez utiliser Chemin objet:

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())

Méthode cwd ()

  

Retourne un nouvel objet chemin représentant le répertoire en cours (tel que retourné par os.getcwd ())

Méthode de résolution ()

  

Rendez le chemin absolu en résolvant les liens symboliques. Un nouvel objet de chemin est renvoyé:

Si vous souhaitez récupérer le chemin racine du package à partir de l'un de ses modules, les opérations suivantes (testées sur Python 3.6):

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

Le chemin principal __ init __. py peut également être référencé en utilisant __ fichier __ à la place.

J'espère que ça aide!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top