Python - ModuleNotFoundError: модуль не указан - PullRequest
1 голос
/ 30 апреля 2020

Я новичок в Python, и у меня возникла следующая ошибка в этом простом примере:

Это структура моего проекта:

python_project
.
├── lib
│   ├── __init__.py
│   └── my_custom_lib.py
└── src
    ├── __init__.py
    └── main.py

И это ошибка когда я выполняю файл src/main.py:

☁  python_project  python src/main.py

Traceback (most recent call last):
  File "src/main.py", line 3, in <module>
    from lib import my_custom_lib
ImportError: No module named lib

Если я перемещаю файл main.py в root, а затем снова запускаю этот файл, работает ... но не работает внутри src/ directory

Это мой main.py:

from lib import my_custom_lib

def do_something(message):
        my_custom_lib.show(message)

do_something('Hello World!')

Примечание: Когда я выполняю тот же код из Pycharm работает нормально, но не из моего терминала.

Ответы [ 4 ]

2 голосов
/ 01 мая 2020

Ваш PYTHONPATH установлен в текущий каталог из программы, которую вы выполняете. Поэтому, если вы выполняете что-то внутри каталога src, он никогда не сможет найти каталог lib, потому что он находится вне пути. Есть несколько вариантов:

  • Просто переместите lib/ в src/, если он принадлежит вашему коду. Если это внешний пакет, он должен быть установлен в pip, как упомянул Энрике Бранко.
  • Иметь скрипт верхнего уровня вне src/, который импортирует и запускает src.main. Это добавит каталог верхнего уровня к пути python.
  • В src/main.py измените sys.path, чтобы включить каталог верхнего уровня. Обычно это вызывает недовольство.
  • Вызывает src/main.py как модуль с python -m src.main, который добавляет каталог верхнего уровня к пути python. Немного раздражает, когда вы набираете текст, плюс вам нужно будет изменить весь ваш импорт.
1 голос
/ 01 мая 2020

Если я могу добавить к MarkM ответ , если вы хотите сохранить свою текущую структуру каталогов и все еще заставить ее работать, вы можете добавить setup.py в свой root каталог, где вы можете использовать setuptools для создания пакета, который вы можете установить.

Если в вашем файле есть что-то вроде:

# setup.py

from setuptools import find_packages, setup

setup(
  name='foo',
  version=`1.0.0`,
  packages=find_packages(),
  entrypoints={
    'console_scripts': [
      'foo=src.main:main',
    ],
  },
)

И тогда вы выполните pip install [--user] -e path/to/directory, и вы получите «редактируемый пакет», который фактически будет символической ссылкой на пакет в вашем каталоге разработки, поэтому любые внесенные вами изменения не потребуют переустановки (если, конечно, вы не изменили структуру пакета или не добавили / удалили / отредактировали точки входа).

Это предполагает, что ваш src/main.py имеет основную функцию.

Вам также понадобятся __init__.py файлы в ваших каталогах "package", даже в Python3, так как в противном случае Python предполагает, что они являются пакетами пространства имен (не будем go подробно), и вызов find_packages() не найдет их.

Это также позволит вашему относительному импорту работать. Абсолютный импорт будет работать только при вызове сценария из вашей точки входа, но не при вызове сценария непосредственно в каталоге разработки.

1 голос
/ 30 апреля 2020

Вы используете from a import b неправильно. он должен выглядеть следующим образом:

import lib.my_custom_lib

Другой метод используется для импорта определенных методов, функций и классов из модуля, а не самого модуля. Чтобы импортировать указанную c функцию из модуля my_custom_lib, она должна выглядеть следующим образом:

from lib.my_custom_lib import foo
0 голосов
/ 30 апреля 2020

Попробуйте вместо этого использовать относительный импорт:

from ..lib import my_custom_lib

...