Importer des fichiers à partir d'un autre dossier
j'ai la structure de dossier suivante.
application/app/folder/file.py
et je veux importer quelques fonctions de file.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 diverses, mais jusqu'à présent, je ne parvenais pas à importer correctement. Comment puis-je faire cela?
21 réponses
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 d'où le script d'entrée s'exécute, et sys.path
qui inclut des localisations telles que le répertoire d'installation du paquet (c'est en fait un peu plus complexe que cela, mais cela 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 que dossier contient aussi un __init__.py , ce qui permet de l'inclure dans un paquet. Je ne sais pas pourquoi les autres réponses parlent de PYTHONPATH.
quand 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 abréviation rend un module visible à l'autre:
import sys
sys.path.append('../')
je pense qu'une façon ad hoc serait d'utiliser la variable d'environnement PYTHONPATH
comme décrit dans la documentation: Python2 , Python3
# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH
# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
De ce que je sais, ajouter un __init__.py
fichier directement dans le dossier des fonctions que vous souhaitez importer fera le travail.
les réponses ici manquent de clarté, ceci est testé sur Python 3.6
avec cette structure de chemise:
main.py
|
---- myfolder/myfile.py
où myfile.py
a le contenu:
def myfunc():
print('hello')
la déclaration d'importation dans main.py
est:
from myfolder.myfile import myfunc
myfunc()
et ceci imprimera hello .
considérant application
comme le répertoire racine de votre projet python, créez un fichier __init__.py
vide dans les répertoires application
, app
et folder
. Puis dans votre some_file.py
faites les changements suivants 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()
a travaillé pour moi en python3 sur linux
import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
votre problème est que Python cherche dans le répertoire Python ce fichier et ne le trouve pas. Vous devez spécifier que vous parlez du répertoire dans lequel vous êtes et non de celui de Python.
pour faire ceci vous changez ceci:
from application.app.folder.file import func_name
à ceci:
from .application.app.folder.file import func_name
en ajoutant le point vous dites regarder dans ce dossier pour le dossier d'application au lieu de regarder dans le Python répertoire.
Première import sys
import sys
Deuxième ajouter le chemin du dossier
sys.path.insert(0, '/the/folder/path/name-folder/')
Third faire un fichier blanc appelé __ init __.py dans votre sous-répertoire (cela indique à Python que c'est un module)
- name-file.py
- nom-dossier
- _ _ init __.1519210920"
- name-module.py
- nom-dossier
Quatrième importer le module à l'intérieur du dossier
from name-folder import name-module
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
Essayer Python relative des importations:
from ...app.folder.file import func_name
chaque point dirigeant est un autre niveau supérieur dans la hiérarchie commençant par le répertoire courant.
problèmes? Si cela ne fonctionne pas pour vous, alors vous êtes probablement mordu par les nombreuses importations relatives de gotcha A. Lire les réponses et les commentaires pour plus de détails: Comment réparer "Tentée par rapport à l'importation de non-package" même avec __init__.py
indice: avoir __init__.py
à chaque niveau de répertoire. Vous pourriez avoir besoin de python -m application.app2.some_folder.some_file
(départ .py) que vous exécutez à partir du répertoire de haut niveau ou que vous avez ce répertoire de haut niveau dans votre PYTHONPATH. Phew!
utilisant sys.chemin.ajouter avec un chemin absolu n'est pas idéal pour déplacer l'application vers d'autres environnements. Utiliser un chemin relatif ne fonctionnera pas toujours car le répertoire de travail actuel dépend de la façon dont le script a été invoqué.
puisque la structure du dossier d'application est fixe, nous pouvons utiliser os.chemin d'accès pour obtenir le chemin complet du module, on souhaite importer. 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 pour importer le module" mango". Vous pouvez faire ce qui suit en 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 le os.chemin de la documentation.
si le but de charger un module à partir d'un chemin spécifique est de vous aider 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 OS moderne qui supporte des liens symboliques.
L'un des avantages de cette approche est que vous pouvez pointer vers un module qui se trouve dans votre copie de travail locale SVC branch, ce qui peut grandement simplifier le cycle de développement et réduire les modes de défaillance de la gestion des différentes versions du module.
je suis assez spécial : J'utilise Python avec Windows !
Je ne fais que compléter l'information : Pour Windows et Linux, les chemins relatifs et absolus fonctionnent en sys.path
(j'ai besoin de chemins relatifs parce que 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 Python cordes,
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 de \
, même si c'est moins "Windows natif" parce que c'est Linux-compatible et plus simple à écrire et copie de l'explorateur Windows)
alors j'ai cliqué à droite sur mon IDE, et j'ai ajouté un nouveau folder
et je me demandais pourquoi je n'étais pas en mesure d'importer de celui-ci. Plus tard, j'ai réalisé que je devais faire un clic droit et créer un paquet Python, et non un dossier classic du système de fichiers. Ou une méthode post-mortem en ajoutant un __init__.py
(qui fait que python traite le dossier du système de fichiers comme un paquet) comme mentionné dans d'autres réponses. Ajouter cette réponse ici juste au cas où quelqu'un aurait pris cette route.
vous pouvez rafraîchir le shell Python en appuyant sur f5, ou aller à Run-> Run Module. De cette façon, vous n'avez pas à changer le répertoire pour lire quelque chose du fichier. Python changera automatiquement le répertoire. Mais si vous voulez travailler avec différents fichiers de différents répertoires dans L'interpréteur de commandes de Python, alors vous pouvez changer le répertoire dans sys, comme Cameron l'a dit plus tôt .
dans mon cas, j'avais une classe à importer. Mon dossier ressemblait à ceci:
# /opt/path/to/code/log_helper.py
class LogHelper:
# stuff here
Dans mon fichier principal, j'ai inclus le code par:
path.append("/opt/path/to/code/")
from log_helper import LogHelper
en Python 3.4 et plus tard, vous pouvez importer à partir d'un fichier source directement (lien vers la documentation) .
voici un exemple. Premièrement, le fichier à importer, appelé foo.py
:
def announce():
print("Imported!")
Le code qui importe le fichier ci-dessus, fortement inspiré par l'exemple dans la documentation:
import importlib, importlib.util, os.path
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
foo = module_from_file("foo", "/path/to/foo.py")
if __name__ == "__main__":
print(foo)
print(dir(foo))
foo.announce()
La sortie:
<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
notez que le nom de la variable, le le nom du module et le nom du fichier ne doivent pas nécessairement correspondre. Ce code fonctionne toujours:
import importlib, importlib.util, os.path
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
baz = module_from_file("bar", "/path/to/foo.py")
if __name__ == "__main__":
print(baz)
print(dir(baz))
baz.announce()
La sortie:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
modules d'importation programmatique a été introduit en python 3.1 et vous donne plus de contrôle sur la façon dont les modules sont importés. Reportez-vous à la documentation pour plus d'informations.
j'ai été confronté au même défi, en particulier lors de l'importation de plusieurs fichiers, c'est comment j'ai réussi à le surmonter.
import os, sys
from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
from root_folder import file_name