Python: ModuleNotFoundError при попытке импортировать модуль из импортированного пакета - PullRequest
0 голосов
/ 08 февраля 2019

Я использую Python 3.7.1 в macOS Mojave версии 10.14.1

Это моя структура каталогов:

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

man1.py содержит следующее import *Оператор 1008 *, который я не хочу менять :

from Soft.SoftWork.manModules import *

man1test.py содержит следующие операторы import :

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

Мне нужен второй импорт в man1test.py, потому что man1test.py нужен доступ к функции в man1.py.

Мое обоснование первого импорта ( Soft ) должен был упростить вышеупомянутый оператор import в man1.py.

Вопреки моим ожиданиям, оператор import в man1.py приводит к:

ModuleNotFoundError: No module named 'Soft'

, когда я запускаю

python3 -m man.MansTest.Unittests.man1test

из каталога выше man / .

Есть ли способ устранить эту ошибку без изменения import оператор в man1.py и без добавления чего-либо в sys.path ?

Редактировать: python3 -m man.ManTest.Unittests.man1test из исходной версии thВопрос изменен на python3 -m man.MansTest.Unittests.man1test

1 Ответ

0 голосов
/ 10 февраля 2019

Есть пара , которые путают требования с вашей настройкой, но я постараюсь дать вам то, что вы хотите.

FIRST , если вы хотите бытьвозможность доступа man1.py из man1test.py И manModules.py из man1.py , необходимо правильно настроить файлыas пакеты и модули .

Пакеты - это способ структурировать пространство имен модулей Python с помощью «точечных имен модулей».Например, имя модуля A.B обозначает подмодуль с именем B в пакете с именем A.

...

При импорте пакета Python просматривает каталоги наsys.path ищет подкаталог пакета.

Файлы __init__.py необходимы, чтобы Python рассматривал каталоги как содержащие пакеты;это сделано для того, чтобы каталоги с общим именем, такие как string, не могли непреднамеренно скрывать действительные модули, которые появляются позже в пути поиска модулей.

Вам необходимо настроить его на что-то вроде этого:

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

SECOND , для ошибки "ModuleNotFoundError: No module named 'Soft'", вызванной from ...Mans import man1 в man1test.py , документированное решение к которой заключается в добавлении man1.py до sys.path, поскольку Mans находится вне пакета MansTest .См. Путь поиска модуля в документации по Python.Но если вы не хотите изменять sys.path напрямую, вы также можете изменить PYTHONPATH:

sys.path инициализируется из следующих мест:

  • каталог, содержащий входной скрипт (или текущий каталог, если файл не указан).
  • PYTHONPATH (список имен каталогов с тем же синтаксисом, что и для переменной оболочки PATH).
  • Зависит от установки по умолчанию.

THIRD , для from ...MansTest.SoftLib import Soft, который вы сказали " должен был облегчить вышеупомянутый оператор импортав man1.py", теперь работает импорт.Если вы хотите импортировать Soft.SoftLib в man1.py , вам нужно настроить man1.py , чтобы найти Soft.SoftLib иимпортируйте его туда напрямую.

С учетом сказанного, вот как я заставил его работать.

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()

manMo средиуфайлы.Это какой-то "мост" между man1.py и man1test.py ?То, как ваши файлы настроены прямо сейчас, я не думаю, что это будет работать так, как вы ожидаете.Кроме того, немного смущает то, что тестируемый код ( man1.py ) импортирует данные из папки теста ( MansTest ).

...