J'ai la structure de dossier suivante.
application/app/folder/file.py
et je veux importer des 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 mais je n'ai pas réussi jusqu'ici à importer correctement. Comment puis-je faire ceci?
Par défaut, vous ne pouvez pas. Lors de l'importation d'un fichier, Python ne recherche que le répertoire en cours, le répertoire à partir duquel le script de point d'entrée est exécuté, et sys.path
, qui comprend des emplacements tels 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 au moment de l'exécution:
# some_file.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')
import file
Rien à redire avec:
from application.app.folder.file import func_name
Assurez-vous simplement que folder
contient également un __init__.py
, cela lui permet d'être inclus dans un package. Vous ne savez 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
Ce raccourci rend un module visible à l'autre:
import sys
sys.path.append('../')
Je pense qu'un moyen ad-hoc serait d'utiliser la variable d'environnement PYTHONPATH
comme décrit dans la documentation: Python2 , Python
# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH
# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Premier système d'importation
import sys
Second ajoute le chemin du dossier
sys.path.insert(0, '/the/folder/path/name-folder/')
Troisième Créez un fichier vierge appelé __ init __.py dans votre sous-répertoire (cela indique que Python est un module)
Quatrième importer le module dans le dossier
from name-folder import name-module
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 vous trouvez et non du 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 indiquez, recherchez dans le dossier de l'application le dossier de l'application plutôt que dans le répertoire Python.
Les réponses ici manquent de clarté, ceci est testé sur Python 3.6
Avec cette structure de dossier:
main.py
|
---- myfolder/myfile.py
Où myfile.py
a le contenu:
def myfunc():
print('hello')
L'instruction d'importation dans main.py
est la suivante:
from myfolder.myfile import myfunc
myfunc()
et cela affichera bonjour .
De ce que je sais, ajouter un fichier __init__.py
directement dans le dossier des fonctions que vous souhaitez importer fera le travail.
En considérant application
comme répertoire racine de votre projet python, créez un fichier __init__.py
vide dans les dossiers application
, app
et folder
. Ensuite, dans votre some_file.py
apportez les modifications comme suit 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()
J'ai été confronté au même défi, en particulier lors de l'importation de plusieurs fichiers. C'est ainsi que 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
A travaillé pour moi en python3 sur linux
import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
Dans Python 3.4 et versions ultérieures, vous pouvez importer directement à partir d'un fichier source (lien vers la documentation) . Ce n'est pas la solution la plus simple, mais j'inclus cette réponse par souci d'exhaustivité.
Voici un exemple. Tout d’abord, le fichier à importer, nommé foo.py
:
def announce():
print("Imported!")
Le code qui importe le fichier ci-dessus, largement inspiré de l'exemple de la documentation:
import importlib.util
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 __== "__main__":
print(foo)
print(dir(foo))
foo.announce()
Le résultat:
<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 nom du module et le nom du fichier ne doivent pas nécessairement correspondre. Ce code fonctionne toujours:
import importlib.util
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 __== "__main__":
print(baz)
print(dir(baz))
baz.announce()
Le résultat:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
L'importation de modules par programme a été introduite dans Python 3.1 et vous donne davantage de contrôle sur la manière dont les modules sont importés. Reportez-vous à la documentation pour plus d'informations.
Essayez les importations relatives de Python:
from ...app.folder.file import func_name
Chaque point en tête est un autre niveau supérieur de la hiérarchie commençant par le répertoire actuel.
Problèmes? Si cela ne fonctionne pas pour vous, alors vous êtes probablement pris au dépourvu par les nombreuses importations relatives de Gotcha. Lisez les réponses et les commentaires pour plus de détails: Comment réparer "Tentative d'importation relative dans un non-package" même avec __init __. Py
Astuce: ayez __init__.py
à chaque niveau de répertoire. Vous aurez peut-être besoin de python -m application.app2.some_folder.some_file
(en laissant de côté .py) que vous exécutez à partir du répertoire de niveau supérieur ou que ce répertoire de niveau supérieur se trouve dans votre PYTHONPATH. Ouf!
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
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 fonctionnera pas toujours car le répertoire de travail en cours dépend de la façon dont le script a été appelé.
Puisque la structure du dossier de l'application est fixe, nous pouvons utiliser os.path pour obtenir le chemin complet du module que nous souhaitons importer. Par exemple, s'il s'agit de 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 pouvez 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 consultez la documentation os.path .
Je suis assez spécial: j'utilise Python avec Windows!
Je viens juste de compléter les informations: pour Windows et Linux, les chemins relatifs et absolus fonctionnent dans sys.path
(j'ai besoin de chemins relatifs, car j'utilise mes scripts sur plusieurs PC et dans différents répertoires principaux).
Et lorsque vous utilisez Windows, \
et /
peuvent être utilisés comme séparateur de noms de fichiers et vous devez bien entendu doubler \
dans Python chaînes,
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 \
, même s'il est moins 'natif de Windows' car compatible avec Linux, il est plus simple d'écrire et de copier dans l'explorateur Windows)
Si le but du chargement d'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 tout autre module installé du même nom pour tout script exécuté dans ce dossier.
J'ai testé cela sous Linux, mais cela devrait fonctionner dans tout système d'exploitation moderne prenant en charge les liens symboliques.
Un avantage de cette approche est que vous pouvez pointer sur un module qui se trouve dans votre propre copie de travail de branche SVC locale, ce qui simplifie grandement le temps de cycle de développement et réduit les modes de défaillance de la gestion des différentes versions du module.
Dans mon cas, j'avais une classe à importer. Mon fichier ressemblait à ceci:
# /opt/path/to/code/log_helper.py
class LogHelper:
# stuff here
Dans mon fichier principal, j'ai inclus le code via:
path.append("/opt/path/to/code/")
from log_helper import LogHelper
Je travaillais sur le projet a
que je voulais que les utilisateurs installent via pip install a
avec la liste de fichiers suivante:
.
├── setup.py
├── MANIFEST.in
└── a
├── __init__.py
├── a.py
└── b
├── __init__.py
└── b.py
setup.py
from setuptools import setup
setup (
name='a',
version='0.0.1',
packages=['a'],
package_data={
'a': ['b/*'],
},
)
MANIFEST.in
recursive-include b *.*
a/init. py
from __future__ import absolute_import
from a.a import cats
import a.b
a/a.py
cats = 0
a/b/init. py
from __future__ import absolute_import
from a.b.b import dogs
a/b/b.py
dogs = 1
J'ai installé le module en lançant ce qui suit à partir du répertoire avec MANIFEST.in
:
python setup.py install
Ensuite, à partir d’un emplacement totalement différent sur mon système de fichiers /moustache/armwrestle
, j’ai pu exécuter:
import a
dir(a)
Ce qui a confirmé que a.cats
était bien égal à 0 et a.b.dogs
était égal à 1, comme prévu.
Vous pouvez actualiser le shell Python en appuyant sur f5 ou aller à Exécuter-> Exécuter le module. De cette façon, vous n'avez pas à changer de répertoire pour lire quelque chose dans le fichier. Python changera automatiquement le répertoire. Mais si vous souhaitez utiliser différents fichiers provenant de différents répertoires dans le shell Python, vous pouvez modifier le répertoire dans sys, comme l'a dit Cameron plus tôt.
Donc, je venais juste de cliquer sur mon IDE et d'ajouter un nouveau folder
et je me demandais pourquoi je ne pouvais pas importer à partir de celui-ci. Plus tard, j'ai réalisé que je devais faire un clic droit et créer un package Python, et non un dossier de système de fichiers classique. Ou une méthode post-mortem ajoutant un __init__.py
(ce qui oblige python à traiter le dossier du système de fichiers comme un paquet), comme indiqué dans d'autres réponses. Ajout de cette réponse ici juste au cas où quelqu'un irait par cette voie.
Vous pouvez utiliser importlib pour importer des modules dans lesquels vous souhaitez importer un module depuis un dossier en utilisant une chaîne telle que:
import importlib
scriptName = 'Snake'
script = importlib.import_module('Scripts\\.%s' % scriptName)
Cet exemple a un fichier main.py qui est le code ci-dessus, puis un dossier appelé Scripts. Vous pouvez ensuite appeler tout ce dont vous avez besoin depuis ce dossier en modifiant la variable scriptName
. Vous pouvez ensuite utiliser script
pour faire référence à ce module. Par exemple, si j'ai une fonction appelée Hello()
dans le module Snake, vous pouvez exécuter cette fonction de la manière suivante:
script.Hello()
J'ai testé cela dans Python 3.6