python - Importer des fichiers de différents dossiers


J'ai la structure de dossier suivante.

application/app/folder/file.py

et je veux importer certaines fonctions de fichier.py dans un autre fichier Python qui réside dans

application/app2/some_folder/some_file.py

J'ai essayé

from application.app.folder.file import func_name

et quelques autres tentatives, mais je n'ai pas réussi à importer correctement. Comment puis-je faire ceci?



Answers



Par défaut, vous ne pouvez pas. Lors de l'importation d'un fichier, Python ne recherche que le répertoire courant, le répertoire dans lequel s'exécute le script d'entrée, et sys.path qui inclut des emplacements tels que le répertoire d'installation du paquet (c'est en fait un peu plus complexe, mais ça couvre la plupart des cas).

Cependant, vous pouvez ajouter au chemin Python à l'exécution:

# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')

import file



Rien de mal avec:

from application.app.folder.file import func_name

Assurez-vous simplement que le dossier contient également un __init__.py , cela lui permet d'être inclus en tant que paquet. Je ne sais pas pourquoi les autres réponses parlent de PYTHONPATH.




Lorsque les modules sont dans des emplacements parallèles, comme dans la question:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

Cette sténographie rend un module visible à l'autre:

import sys
sys.path.append('../')



Puisque votre question semble spécifique à * nix, je pense que la méthode propre consisterait à utiliser la variable d'environnement

PYTHONPATH

comme décrit dans la documentation: Python2 , Python3

export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH



De ce que je sais, ajouter un fichier __init__.py directement dans le dossier des fonctions que vous souhaitez importer fera le travail.




A travaillé pour moi dans python3 sur Linux

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  



En considérant l' application comme répertoire racine pour votre projet python, créez un fichier __init__.py vide __init__.py dossiers d' application , d' app et de dossiers. Puis, dans votre some_file.py effectuez les modifications suivantes pour obtenir la définition de func_name:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()



Cela fonctionne pour moi sur Windows

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file



Si le but du chargement d'un module à partir d'un chemin spécifique est de vous assister lors du développement d'un module personnalisé, vous pouvez créer un lien symbolique dans le même dossier du script de test qui pointe vers la racine du module personnalisé. Cette référence de module aura la priorité sur tous les autres modules installés du même nom pour tout script exécuté dans ce dossier.

J'ai testé cela sur Linux mais cela devrait fonctionner dans n'importe quel système d'exploitation moderne qui supporte les liens symboliques.

Un avantage de cette approche est que vous pouvez pointer vers un module qui se trouve dans votre propre copie de travail locale de la branche SVC, ce qui peut grandement simplifier le cycle de développement et réduire les modes de gestion des différentes versions du module.




Votre problème est que Python cherche dans le répertoire Python pour ce fichier et ne le trouve pas. Vous devez spécifier que vous parlez du répertoire dans lequel vous êtes et non du répertoire Python.

Pour ce faire, vous changez ceci:

from application.app.folder.file import func_name

pour ça:

from .application.app.folder.file import func_name

En ajoutant le point que vous dites regardez dans ce dossier pour le dossier de l'application au lieu de chercher dans le répertoire Python.

(J'espère que cela résout votre problème!)




Je suis assez spécial: j'utilise Python avec Windows!

Je viens de compléter l'information: pour Windows et Linux, le chemin relatif et le chemin absolu fonctionnent dans sys.path (j'ai besoin de chemins relatifs car j'utilise mes scripts sur plusieurs PC et sous différents répertoires principaux).

Et lorsque vous utilisez Windows, \ et / peuvent être utilisés comme séparateur pour les noms de fichiers et bien sûr vous devez doubler \ en chaînes Python,
quelques exemples valables:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(note: je pense que / est plus pratique que \ , événement s'il est moins 'natif de Windows' parce qu'il est compatible avec Linux et plus simple à écrire et à copier dans l'explorateur Windows)




L'utilisation de sys.path.append avec un chemin absolu n'est pas idéale lorsque vous déplacez l'application vers d'autres environnements. L'utilisation d'un chemin relatif ne fonctionne pas toujours car le répertoire de travail en cours dépend de l'exécution du script.

Puisque la structure du dossier de l'application est fixe, nous pouvons utiliser os.path pour obtenir le chemin complet. Par exemple, si c'est la structure:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

Et disons que vous voulez importer le module "mangue". Vous pourriez faire ce qui suit dans vanilla.py:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

Bien sûr, vous n'avez pas besoin de la variable mango_dir.

Pour comprendre comment cela fonctionne, regardez cet exemple de session interactive:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

Et vérifiez la documentation de os.path .




Vous pouvez actualiser le shell Python en appuyant sur f5 ou aller à Run-> Run Module. De cette façon, vous n'avez pas besoin de changer le répertoire pour lire quelque chose à partir du fichier. Python changera automatiquement le répertoire. Mais si vous voulez travailler avec différents fichiers provenant de répertoires différents dans le Shell Python, alors vous pouvez changer le répertoire dans sys, comme Cameron l'a dit plus tôt.




sys.path.insert(0, '/path/to/application/app/folder')