Python: ‘ModuleNotFoundError’ bij het importeren van module uit geïmporteerd pakket

Ik gebruik Python 3.7.1 op macOS Mojave versie 10.14.1

Dit is mijn directorystructuur:

man/                          
  Mans/                  
          man1.py
  MansTest/
          SoftLib/
                  Soft/
                      SoftWork/
                              manModules.py
          Unittests/
                    man1test.py

man1.pybevat de volgende import-instructie, die ik niet wil wijzigen:

from Soft.SoftWork.manModules import *

man1test.pybevat de volgende import-instructies:

from ...MansTest.SoftLib import Soft
from ...Mans import man1

Ik heb de tweede importnodig in man1test.pyomdat man1test.pytoegang nodig heeft tot een functie in man1.py.

Mijn grondgedachte achter de eerste import (Soft) was om de bovengenoemde import-instructie in man1.pyte vergemakkelijken.

In tegenstelling tot mijn verwachting geeft het importstatement in man1.pyechter aanleiding tot:

ModuleNotFoundError: No module named 'Soft'

wanneer ik ren

python3 -m man.MansTest.Unittests.man1test

uit een map boven man/.

Is er een manier om deze fout op te lossen zonder de import-instructie in man1.pyente wijzigen zonder iets toe te voegen aan sys .pad?

Bewerken: python3 -m man.ManTest.Unittests.man1testvan de oorspronkelijke versie van de vraag gewijzigd in python3 -m man.MansTest.Unittests.man1test


Antwoord 1, autoriteit 100%

EERST, als u toegang wilt hebben tot man1.pyvanuit man1test.pyEN manModules.pyvan man1.py, moet u uw bestanden correct instellen als pakketten en modules.

Pakketten zijn een manier om de modulenaamruimte van Python te structureren door gebruik te maken van
“gestippelde modulenamen”. De modulenaam A.Bduidt bijvoorbeeld a . aan
submodule met de naam Bin een pakket met de naam A.

Bij het importeren van het pakket zoekt Python door de mappen op
sys.pathop zoek naar de submap van het pakket.

De __init__.pybestanden zijn vereist om Python de . te laten behandelen
directory’s die pakketten bevatten; dit wordt gedaan om te voorkomen
mappen met een algemene naam, zoals string, van onbedoeld
geldige modules verbergen die later in het zoekpad van de module voorkomen.

Je moet het ongeveer als volgt instellen:

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

TWEEDE, voor de “ModuleNotFoundError: No module named 'Soft'” fout veroorzaakt door from ...Mans import man1in man1test.py, de gedocumenteerde oplossing daarvoor is om man1.pytoe te voegen aan sys.pathaangezien Mansbuiten het MansTestpakket. Zie Het modulezoekpaduit de Python-documentatie . Maar als u sys.pathniet rechtstreeks wilt wijzigen, kunt u ook PYTHONPATHwijzigen:

sys.pathwordt geïnitialiseerd vanaf deze locaties:

  • De map met het invoerscript (of de huidige map als er geen bestand is opgegeven).
  • PYTHONPATH(een lijst met directorynamen, met dezelfde syntaxis als de shellvariabele PATH).
  • De installatie-afhankelijke standaard.

THIRD, voor from ...MansTest.SoftLib import Softwaarvan u zei “was om de bovengenoemde importinstructie in man1.py“, zo werkt import nu. Als u Soft.SoftLibin man1.pywilt importeren, moet u man1.pyinstellen om Soft.SoftLiben importeer het daar direct.

Dat gezegd hebbende, hier is hoe ik het werkend heb gekregen.

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"

Terminal-uitgang:

$ 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 

Als een suggestie, misschien denk je het doel van die Softlib -bestanden. Is het een soort van “bridge” tussen Man 1. Py en man1test.py ? De manier waarop uw bestanden nu worden ingesteld, denk ik niet dat het gaat werken terwijl u verwacht dat het is. Het is ook een beetje verwarrend voor de Code-Under-Test (Man 1. Py ) om dingen uit onder de testmap te importeren (MANSTEST ).


Antwoord 2

Voor mij wanneer ik een bestand heb gemaakt en het als Python-bestand heeft opgeslagen, kreeg ik deze fout tijdens het importeren.
Ik moest een bestandsnaam maken met het type “.py”, zoals bestandsnaam.py en vervolgens opslaan als een Python-bestand.
Post proberen om het bestand voor mij te importeren.

Other episodes