Comment importer un module Python compte tenu de son chemin d'accès relatif?
Par exemple, si dirFoo
contient Foo.py
et dirBar
, et dirBar
contient Bar.py
, comment importer Bar.py
dans Foo.py
?
Voici une représentation visuelle:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
souhaite inclure Bar
, mais la restructuration de la hiérarchie des dossiers n'est pas une option.
python
relative-path
python-import
Jude Allred
la source
la source
Réponses:
En supposant que vos deux répertoires sont de vrais packages Python (ils contiennent le
__init__.py
fichier), voici une solution sûre pour l'inclusion de modules relativement à l'emplacement du script.Je suppose que vous voulez le faire, car vous devez inclure un ensemble de modules avec votre script. Je l'utilise en production dans plusieurs produits et fonctionne dans de nombreux scénarios spéciaux comme: des scripts appelés à partir d'un autre répertoire ou exécutés avec python execute au lieu d'ouvrir un nouvel interpréteur.
En prime, cette approche vous permet de forcer Python à utiliser votre module au lieu de ceux installés sur le système.
Attention! Je ne sais pas vraiment ce qui se passe lorsque le module actuel se trouve dans un
egg
fichier. Il échoue probablement aussi.la source
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
N'ajoutez PAS le sous-dossier auparavantabspath
car cela provoque de graves bogues.cmd_subfolder
) directement à ma réponse. Merci!realpath
génère déjà des chemins absolus, donc je n'ai pas besoinabspath
.os.path.dirname
Peut également être utilisé au lieu de scinder, rendant l'indexation[0]
obsolète. La ligne serait alors:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Assurez-vous que dirBar a le
__init__.py
fichier - cela fait un répertoire dans un package Python.la source
sys.path
alors la présence de__init__.py
dans ledirBar
répertoire n'aide pas beaucoup.__init.py__
ne fonctionnera que lorsque le répertoire est déjà dans sys.path et dans mon cas, ce n'était pas le cas. La solution de "sorin" (acceptée) fonctionne toujours.sys.path
provenance de la question? Peut-être y a-t-il eu quelque chose d'omis que nous n'avons pas vu ou connu?Vous pouvez également ajouter le sous-répertoire à votre chemin Python afin qu'il soit importé en tant que script normal.
la source
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
car il chargera ce module avant les modules du même nom stockés ailleurs.la source
os.path.join()
au lieu de rejoindre par '/', qui se brisera dans les fenêtres (boiteuses).os.path.abspath(os.path.join(__file__,'..','lib'))
?Faites simplement des choses simples pour importer le fichier .py à partir d'un dossier différent.
Disons que vous avez un répertoire comme:
Ensuite, gardez simplement un fichier vide dans le dossier lib comme nommé
Et puis utilisez
Conservez le
__init__.py
fichier dans chaque dossier de la hiérarchie du module d'importation.la source
Si vous structurez votre projet de cette façon:
Ensuite, à partir de Foo.py, vous devriez pouvoir faire:
Ou:
Selon le commentaire de Tom, cela nécessite que le
src
dossier soit accessible viasite_packages
ou votre chemin de recherche. De plus, comme il le mentionne,__init__.py
est implicitement importé lorsque vous importez un module dans ce package / répertoire pour la première fois. Il__init__.py
s'agit généralement d' un fichier vide.la source
from dirFoo import Foo
direFoo.bla()
. Si vous en utilisez,import dirFoo.Foo
vous devez utiliserdirFoo.Foo.bla()
- assez moche même sans étui à chameau.La méthode la plus simple consiste à utiliser sys.path.append ().
Cependant, vous pouvez également être intéressé par le module imp . Il donne accès aux fonctions d'importation internes.
Cela peut être utilisé pour charger des modules dynamiquement lorsque vous ne connaissez pas le nom d'un module.
J'ai utilisé cela dans le passé pour créer une interface de type plugin pour une application, où l'utilisateur écrirait un script avec des fonctions spécifiques à l'application, et déposerait simplement son script dans un répertoire spécifique.
De plus, ces fonctions peuvent être utiles:
la source
C'est le PEP pertinent:
http://www.python.org/dev/peps/pep-0328/
En particulier, en supposant que dirFoo est un répertoire à partir de dirBar ...
Dans dirFoo \ Foo.py:
la source
Le moyen le plus simple sans aucune modification de votre script est de définir la variable d'environnement PYTHONPATH. Parce que sys.path est initialisé à partir de ces emplacements:
Exécutez simplement:
Votre sys.path contiendra le chemin ci-dessus, comme indiqué ci-dessous:
la source
À mon avis, le meilleur choix est de mettre __ init __.py dans le dossier et d'appeler le fichier avec
Il n'est pas recommandé d'utiliser sys.path.append () car quelque chose pourrait mal tourner si vous utilisez le même nom de fichier que le package python existant. Je n'ai pas testé cela, mais ce sera ambigu.
la source
from dirBar.Bar import *
fonctionne, mais pasfrom dirBar.Bar import Bar
. savez-vous pourquoi * fonctionne? Et si j'avais plusieurs fichiers dans dirBar / et que je ne voulais en saisir que quelques-uns (en utilisant une méthode comme celle que vous avez publiée ici)?from dirBar import Bar
.from
indique la source, et toutimport
ce qui se trouve après est ce qu'il faut récupérer de cette source.from dirBar.Bar import Bar
signifie "De la source, importez la source elle-même", ce qui n'a pas de sens. le*
bien signifie, "donnez-moi tout de la source"Le moyen rapide et sale pour les utilisateurs de Linux
Si vous ne faites que bricoler et que vous ne vous souciez pas des problèmes de déploiement, vous pouvez utiliser un lien symbolique (en supposant que votre système de fichiers le prend en charge) pour rendre le module ou le package directement visible dans le dossier du module demandeur.
ou
Remarque: Un "module" est n'importe quel fichier avec une extension .py et un "package" est n'importe quel dossier qui contient le fichier
__init__.py
(qui peut être un fichier vide). Du point de vue de l'utilisation, les modules et les packages sont identiques - les deux exposent leurs "définitions et instructions" contenues comme demandé via laimport
commande.Voir: http://docs.python.org/2/tutorial/modules.html
la source
au lieu de:
juste au cas où il pourrait y avoir un autre dirBar installé et confondre un lecteur foo.py.
la source
Pour que ce cas importe Bar.py dans Foo.py, je transformerais d'abord ces dossiers en packages Python comme ceci:
Ensuite, je le ferais comme ça dans Foo.py:
Si je voulais que l'espace de noms ressemble à Bar. quoi que ce soit , ou
Si je voulais le dirBar.Bar d'espacement de noms. peu importe . Ce deuxième cas est utile si vous avez plus de modules sous le package dirBar.
la source
Ajoutez un fichier __init__.py :
Ajoutez ensuite ce code au début de Foo.py:
la source
dirBar
est déjà un paquet Python (par l'existence dedirBar/__init__.py
), il n'y a pas besoin d'ajouterdirBar
àsys.path
, non? La déclarationimport Bar
deFoo.py
devrait suffire.Exemple relatif de sys.path:
Basé sur cette réponse.
la source
Eh bien, comme vous le mentionnez, vous souhaitez généralement avoir accès à un dossier contenant vos modules par rapport à l'emplacement d'exécution de votre script principal, il vous suffit donc de les importer.
Solution:
J'ai le script
D:/Books/MyBooks.py
et quelques modules (comme oldies.py). Je dois importer du sousD:/Books/includes
- répertoire :Placez un
print('done')
inoldies.py
pour vérifier que tout se passe bien. Cette méthode fonctionne toujours car, selon la définition Pythonsys.path
telle qu'initialisée au démarrage du programme, le premier élément de cette liste,path[0]
est le répertoire contenant le script qui a été utilisé pour appeler l'interpréteur Python.Si le répertoire de script n'est pas disponible (par exemple, si l'interpréteur est appelé de manière interactive ou si le script est lu à partir d'une entrée standard),
path[0]
est la chaîne vide, qui dirige Python pour rechercher les modules dans le répertoire actuel en premier. Notez que le répertoire de script est inséré avant les entrées insérées à la suite dePYTHONPATH
.la source
site.addsitedir(sys.path[0]+'/includes')
) dans mon premier programme Python simple break_time.py: https://github.com/ltfschoen/PythonTest . J'utilise le système: MacOS v10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Vous pouvez simplement utiliser:
from Desktop.filename import something
Exemple:
le code:
Mais assurez-vous de créer un fichier vide appelé "
__init__.py
" dans ce répertoirela source
import something
puis je l'ai dit pour le rendre plus facile,*
ce n'est pas bon pour le ram et aussi si 2 fonctions ont le même nom, ilUne autre solution consisterait à installer le package py-require , puis à utiliser ce qui suit dans
Foo.py
la source
require()
fonction, vous pouvez jeter un œil à mon projet Node.pyVoici un moyen d'importer un fichier d'un niveau supérieur, en utilisant le chemin relatif.
Fondamentalement, il suffit de déplacer le répertoire de travail d'un niveau (ou de n'importe quel emplacement relatif), d'ajouter cela à votre chemin, puis de déplacer le répertoire de travail là où il a commencé.
la source
Je ne connais pas le python, donc s'il y a un problème dans mes mots, dites-le moi. Si votre hiérarchie de fichiers est organisée comme ceci:
module_1.py
définit une fonction appeléefunc_1()
, module_2.py :et vous exécutez
python module_2.py
en cmd, il exécutera ce quifunc_1()
définit. C'est généralement ainsi que nous importons les mêmes fichiers de hiérarchie. Mais quand vous écrivezfrom .module_1 import func_1
dansmodule_2.py
, interpréteur Python diraNo module named '__main__.module_1'; '__main__' is not a package
. Donc, pour résoudre ce problème, nous conservons simplement les modifications que nous venons d'apporter, et déplaçons les deux modules dans un package, et créons un troisième module en tant qu'appelant à exécutermodule_2.py
.main.py :
Mais la raison pour laquelle nous ajoutons un
.
avantmodule_1
enmodule_2.py
est que si nous ne le faisons pas et exécutermain.py
, l' interpréteur python va direNo module named 'module_1'
, c'est un peu délicat, quimodule_1.py
est juste à côtémodule_2.py
. Maintenant , je laissefunc_1()
enmodule_1.py
do quelque chose:qui
__name__
enregistre qui appelle func_1. Maintenant, nous gardons l'.
avantmodule_1
, exécutonsmain.py
, il imprimerapackage_1.module_1
, nonmodule_1
. Cela indique que celui qui appellefunc_1()
est dans la même hiérarchie quemain.py
,.
cela implique qu'ilmodule_1
est dans la même hiérarchie quemodule_2.py
lui. Donc, s'il n'y a pas de point,main.py
reconnaîtramodule_1
la même hiérarchie que lui, il peut reconnaîtrepackage_1
, mais pas ce qui est "sous".Maintenant, faisons un peu compliqué. Vous avez un
config.ini
et un module définit une fonction pour le lire dans la même hiérarchie que 'main.py'.Et pour une raison inévitable, vous devez l'appeler avec
module_2.py
, il doit donc importer de la hiérarchie supérieure. module_2.py :Deux points signifie l'importation à partir de la hiérarchie supérieure (trois points d'accès supérieur à supérieur, etc.). Maintenant , nous courons
main.py
, l'interprète dira:ValueError:attempted relative import beyond top-level package
. Le "package de niveau supérieur" ici estmain.py
. Tout simplement parce qu'ils sont àconfig.py
côtémain.py
, ils sont dans la même hiérarchie,config.py
ne sont pas "sous"main.py
, ou ils ne sont pas "dirigés" parmain.py
, donc c'est au-delàmain.py
. Pour résoudre ce problème, le moyen le plus simple est:Je pense que cela coïncide avec le principe de l'organisation de la hiérarchie des fichiers de projet, vous devez organiser les modules avec différentes fonctions dans différents dossiers, et laisser simplement un appelant supérieur à l'extérieur, et vous pouvez importer comme vous le souhaitez.
la source
Cela fonctionne également, et est beaucoup plus simple que tout avec le
sys
module:la source
Appelez-moi trop prudent, mais j'aime rendre le mien plus portable car il n'est pas sûr de supposer que les fichiers seront toujours au même endroit sur chaque ordinateur. Personnellement, le code recherche d'abord le chemin du fichier. J'utilise Linux donc le mien ressemblerait à ceci:
C'est bien sûr à moins que vous ne prévoyiez de les regrouper. Mais si c'est le cas, vous n'avez pas vraiment besoin de deux fichiers distincts de toute façon.
la source