J'utilise Python 3.7.1 sur macOS Mojave version 10.14.1
Voici ma structure de répertoires:
man/
Mans/
man1.py
MansTest/
SoftLib/
Soft/
SoftWork/
manModules.py
Unittests/
man1test.py
man1.py
contient les instructions import, que je ne veux pas changer:
from Soft.SoftWork.manModules import *
man1test.py
contient les instructions import suivantes:
from ...MansTest.SoftLib import Soft
from ...Mans import man1
J'ai besoin du second import in man1test.py
car man1test.py
a besoin d'accéder à une fonction dans man1.py
.
Mon raisonnement derrière la première importation (Soft) était de faciliter la déclaration import susmentionnée dans man1.py
.
Contrairement à mes attentes, cependant, l'instruction import dans man1.py
donne lieu à:
ModuleNotFoundError: No module named 'Soft'
quand je cours
python3 -m man.MansTest.Unittests.man1test
à partir d'un répertoire ci-dessus man /.
Existe-t-il un moyen de résoudre cette erreur sans modifier l'instruction import dans man1.py
et sans rien ajouter à sys.path?
Éditer: python3 -m man.ManTest.Unittests.man1test
de la version originale de la question a été remplacé par python3 -m man.MansTest.Unittests.man1test
Il y a quelques source de confusion avec votre configuration mais je vais essayer de vous donner ce que vous voulez.
[~ # ~] d'abord [~ # ~] , si vous voulez pouvoir accéder à man1.py from man1test.py AND manModules.py from man1.py, vous devez configurer correctement vos fichiers comme - packages et modules .
Les packages sont un moyen de structurer l'espace de noms des modules de Python en utilisant des "noms de modules en pointillés". Par exemple, le nom du module
A.B
désigne un sous-module nomméB
dans un package nomméA
....
Lors de l'importation du package, Python recherche dans les répertoires sur
sys.path
recherche du sous-répertoire du package.Le
__init__.py
les fichiers sont nécessaires pour que Python traite les répertoires comme contenant des packages; cela est fait pour empêcher les répertoires avec un nom commun, commestring
, de masquer involontairement des modules valides qui se produire plus tard sur le chemin de recherche du module.
Vous devez le configurer pour quelque chose comme ceci:
man
|- __init__.py
|- Mans
|- __init__.py
|- man1.py
|- MansTest
|- __init.__.py
|- SoftLib
|- Soft
|- __init__.py
|- SoftWork
|- __init__.py
|- manModules.py
|- Unittests
|- __init__.py
|- man1test.py
[~ # ~] seconde [~ # ~] , pour le "ModuleNotFoundError: No module named 'Soft'
"erreur provoquée par from ...Mans import man1
in man1test.py, la solution documentée à cela consiste à ajouter man1.py à sys.path
puisque Mans est en dehors du package MansTest. Voir Le chemin de recherche du module dans la documentation Python. Mais si vous ne voulez pas modifier sys.path
directement, vous pouvez également modifier PYTHONPATH
:
sys.path
est initialisé à partir de ces emplacements:
- Le répertoire contenant le script d'entrée (ou le répertoire courant lorsqu'aucun fichier n'est spécifié).
PYTHONPATH
(une liste de noms de répertoires, avec la même syntaxe que la variable ShellPATH
).- Valeur par défaut dépendante de l'installation.
[~ # ~] troisième [~ # ~] , pour from ...MansTest.SoftLib import Soft
dont vous avez dit " devait faciliter la déclaration d'importation susmentionnée dans man1.py", c'est maintenant ainsi que les importations fonctionnent. Si vous souhaitez importer Soft.SoftLib dans man1.py, vous devez configurer man1.py pour trouver = Soft.SoftLib et importez-le directement.
Cela dit, voici comment je l'ai fait fonctionner.
man1.py:
from Soft.SoftWork.manModules import *
# no change to import statement but need to add Soft to PYTHONPATH
def foo():
print("called foo in man1.py")
print("foo call module1 from manModules: " + module1())
man1test.py
# no need for "from ...MansTest.SoftLib import Soft" to facilitate importing..
from ...Mans import man1
man1.foo()
manModules.py
def module1():
return "module1 in manModules"
Sortie borne:
$ python3 -m man.MansTest.Unittests.man1test
Traceback (most recent call last):
...
from ...Mans import man1
File "/temp/man/Mans/man1.py", line 2, in <module>
from Soft.SoftWork.manModules import *
ModuleNotFoundError: No module named 'Soft'
$ PYTHONPATH=$PYTHONPATH:/temp/man/MansTest/SoftLib
$ export PYTHONPATH
$ echo $PYTHONPATH
:/temp/man/MansTest/SoftLib
$ python3 -m man.MansTest.Unittests.man1test
called foo in man1.py
foo called module1 from manModules: module1 in manModules
À titre de suggestion, peut-être repenser le but de ces fichiers SoftLib. Est-ce une sorte de "pont" entre man1.py et man1test.py? La façon dont vos fichiers sont configurés en ce moment, je ne pense pas que cela fonctionnera comme vous vous attendez. En outre, il est un peu déroutant pour le code en cours de test ( man1.py) d'importer des éléments sous le dossier de test ( MansTest).