«ModuleNotFoundError» после установки пакета Python

Краткое описание проблемы

Я очень новичок в разработке пакетов Python. Я разработал пакет и опубликовал его на TestPyPI. Я устанавливаю этот пакет через pip без ошибок. Однако python выдает мне «ModuleNotFoundError», когда я пытаюсь его импортировать, и я понятия не имею, почему. Кто-нибудь может мне помочь?

Шаги воспроизведения

Сначала я устанавливаю пакет с:

pip install -i https://test.pypi.org/simple/ spark-map==0.2.76

Затем я открываю новый терминал, запускаю интерпретатор Python и пытаюсь импортировать этот пакет, но Python выдает мне ModuleNotFoundError:

>>> import spark_map
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'spark_map'

Что я открываю

  • Когда я cd захожу в корневую папку пакета, открываю интерпретатор Python и запускаю import spark_map, он работает нормально, без ошибок;

  • Что pip не удалось установить пакет; Однако я проверил это. У меня нет сообщений об ошибках при установке пакета, и когда я запускаю pip list после команды pip install, я вижу spark_map в списке установленных пакетов.

> pip list
... many packages
spark-map                0.2.76
... more packages
  • Папка, в которую был установлен spark_map, может быть вне пути поиска модулей Python; Я проверил и это. pip устанавливает пакет в папку с именем Python310\lib\site-packages, и эта папка включена в переменную sys.path:
>>> import sys
>>> for path in sys.path:
...     print(path)

C:\Users\pedro\AppData\Local\Programs\Python\Python310\python310.zip
C:\Users\pedro\AppData\Local\Programs\Python\Python310\DLLs
C:\Users\pedro\AppData\Local\Programs\Python\Python310\lib
C:\Users\pedro\AppData\Local\Programs\Python\Python310
C:\Users\pedro\AppData\Local\Programs\Python\Python310\lib\site-packages
C:\Users\pedro\AppData\Local\Programs\Python\Python310\lib\site-packages\win32
C:\Users\pedro\AppData\Local\Programs\Python\Python310\lib\site-packages\win32\lib
C:\Users\pedro\AppData\Local\Programs\Python\Python310\lib\site-packages\Pythonwin

Информация о системе

Я на Windows 10, Python 3.10.9, пытаюсь установить и импортировать пакет spark_map версии 0.2.76.(https://test.pypi.org/project/spark-map/).

Информация о коде

Исходный код пакета размещен на GitHub, и структура папок этого пакета по сути такова:

root
│
├───spark_map
│   ├───__init__.py
│   ├───functions.py
│   └───mapping.py
│
├───tests
│   ├───functions
│   └───mapping
│
├───.gitignore
├───LICENSE
├───pyproject.toml
├───README.md
└───README.rst

pyproject.toml файл пакета:

[build-system]
requires = ["setuptools>=61.0", "toml"]
build-backend = "setuptools.build_meta"

[project]
name = "spark_map"
version = "0.2.76"
authors = [
  { name = "Pedro Faria", email = "[email protected]" }
]
description = "Pyspark implementation of `map()` function for spark DataFrames"
readme = "README.md"
requires-python = ">=3.7"
license = { file = "LICENSE.txt" }
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

dependencies = [
    "pyspark",
    "setuptools",
    "toml"
]

[project.urls]
Homepage = "https://pedropark99.github.io/spark_map/"
Repo = "https://github.com/pedropark99/spark_map"
Issues = "https://github.com/pedropark99/spark_map/issues"


[tool.pytest.ini_options]
pythonpath = [
  "."
]


[tool.setuptools]
py-modules = []

Что я пробовал

Как предложил @Dorian Turba, я переместил исходный код в папку src. Теперь структура пакета такова:

root
├───src
│   └───spark_map
│       ├───__init__.py
│       ├───functions.py
│       └───mapping.py
│
├───tests
├───.gitignore
├───LICENSE
├───pyproject.toml
├───README.md
└───README.rst

После этого я выполнил python -m pip install -e . (лог этой команды на картинке ниже). Пакет был скомпилирован и успешно установлен. Однако, когда я открываю новый терминал в другом месте и пытаюсь запустить python -c "import spark_map", я все равно получаю ту же ошибку.

Я также попытался запустить виртуальную среду (с помощью python -m venv env) и установить пакет внутри этой виртуальной среды (с помощью pip install -e .). Затем я выполнил python -c "import spark_map". Но проблема все еще остается. Я также выполнил pip list, чтобы проверить, был ли установлен пакет. Полный лог команд на картинке ниже:

Должен ли путь к модулю быть root/src/spark_map, а не просто root/spark_map?

j123b567 30.01.2023 14:15

Я действительно новичок в этом, поэтому я не знаю, лучший ли это способ. Но я попробую это. Спасибо!

Pedro Faria 30.01.2023 14:19

Отличные детали в вопросе, большое спасибо, если бы все спрашивающие были такими, как вы, это было бы здорово!

Dorian Turba 30.01.2023 14:28

Возможно, этот ответ может вам помочь: stackoverflow.com/questions/71611215/…

Julian Rodríguez 30.01.2023 15:15

В разделе What I tried не могли бы вы поделиться своей новой файловой иерархией, пожалуйста?

Dorian Turba 30.01.2023 16:11

Да! я сделаю это

Pedro Faria 30.01.2023 16:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
6
104
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

требуется папка src

Стандартный макет файла следующий (Документ Python: Упаковка проектов Python):

packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│   └── example_package_YOUR_USERNAME_HERE/
│       ├── __init__.py
│       └── example.py
└── tests/

Вам нужно поместить свой пакет в папку src.

Для вашего проекта это должно выглядеть так:

root
│
├───src/
│   └───spark_map/
│       ├───__init__.py
│       ├───functions.py
│       └───mapping.py
├───tests/
│   ├───functions
│   └───mapping
├───.gitignore
├───LICENSE
├───pyproject.toml
├───README.md
└───README.rst

Вам не нужно создавать дистрибутив колеса, чтобы проверить это, вы можете установить пакет непосредственно в свою среду с помощью pip install . (или в режиме редактирования, если вы хотите, чтобы ваше обновление было доступно напрямую без переустановки pip install -e .).

Рад помочь, у меня было много проблем с подобными вещами, многие из них были из-за невнимательности к деталям!

Dorian Turba 30.01.2023 14:21

Я переместил папку spark_map в папку src и снова скомпилировал проект с помощью python -m build --wheel, а затем установил этот дистрибутив колеса с помощью pip install. Однако проблема все еще остается. Я где-то открываю терминал и интерпретатор python, пытаюсь запустить import spark_map и появляется тот же «ModuleNotFoundError».

Pedro Faria 30.01.2023 14:45

Можете попробовать с pip install -e . ? Вы проверили, находитесь ли вы в правильном окружении Python? у вас есть виртуальная среда? Он активирован?

Dorian Turba 30.01.2023 14:48

Я попробовал эту команду pip install -e . и обновил вопрос с информацией журнала. Но ошибка «ModuleNotFound» все еще остается, когда я пытаюсь ее импортировать.

Pedro Faria 30.01.2023 14:58

@pedro Я не понимаю, почему перенос проекта в src не решил вашу проблему. Исправление, которое вы найдете, просто позволяет вам не использовать файл src, но оно не является стандартным и может сбивать с толку. Вы переместили все файлы дерева в src или всю папку spark_map в src?

Dorian Turba 30.01.2023 16:08

Убедитесь, что вы используете правильную среду Python

  1. Если вы используете виртуальную среду, убедитесь, что она активирована
  2. Убедитесь, что пакет установлен в этой среде (используя pip list).
Ответ принят как подходящий

Источник проблемы

Источник проблемы находится в «процессе сборки» пакета. Другими словами, pip install устанавливал «недопустимый пакет».

По сути, я использую setuptools для сборки пакета. Когда я скомпилировал (или «собрал» пакет с помощью python -m build, исходный код пакета (то есть все содержимое каталога src) не был включен в скомпилированный TAR-архив.

Исправить с помощью setuptools

Документация для setuptools рассказывает об этой проблеме поиска исходного кода для вашего проекта. По сути, setuptools не находил исходный код пакета. Поэтому мне нужно было помочь ему найти эти файлы, добавив эти две опции в мой файл pyproject.toml:

[tool.setuptools]
packages = ["spark_map"]
package-dir = {"" = "src"}

Как можно определить эту проблему?

Если у вас возникла аналогичная проблема при установке и импорте пакета, возможно, у вас возникла та же проблема, что и у меня. Чтобы проверить, так ли это, создайте свой проект с помощью python -m build. Затем откройте исходный дистрибутив вашего пакета (то есть архив TAR) и проверьте, есть ли исходный код внутри этого файла TAR. Если нет, то у вас именно эта проблема.

С вашей добавленной конфигурацией выполняется локальная установка, такая как pip install . работает сейчас?

Dorian Turba 30.01.2023 16:05

Это похоже на обходной путь, чтобы не помещать папку spark_map в src, что не является стандартным. Если это работает, отлично, но я бы не рекомендовал этого, и мы должны заставить его работать со стандартным макетом пакета, если это возможно.

Dorian Turba 30.01.2023 16:10

Да! Когда я добавил эти [tool.setuptools] параметры, локальная установка с pip install -e . работала, и импорт тоже!

Pedro Faria 30.01.2023 16:11

Ага! Я тоже нашел это странным, потому что лучшая практика в приведенной вами документации заключалась в том, чтобы включить пакет в папку src. Итак, я не знаю, ПОЧЕМУ setuptools не может найти исходный код.

Pedro Faria 30.01.2023 16:13

Может быть, я понимаю, почему. Можете ли вы поделиться деревом файлов после перемещения файлов в папке src?

Dorian Turba 30.01.2023 16:18

Я только что добавил это файловое дерево к предыдущему вопросу, но я добавлю его и к этому ответу!

Pedro Faria 30.01.2023 16:18

Можете ли вы попробовать этот ответ? stackoverflow.com/a/75286445/6251742 Я не пользуюсь setuptools, возможно поэтому у меня не получается такой же результат как у вас

Dorian Turba 30.01.2023 16:21

Используйте Hatchling с исходниками в папке src

Измените систему сборки на вылупление

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Вам также необходимо изменить макет вашего проекта, как описано в этом ответе: требуется папка src.

Я протестировал это решение, и оно тоже сработало! Поэтому я тоже добавляю это решение в свой ответ!

Pedro Faria 30.01.2023 16:47

Не редактируйте свой ответ другим содержанием ответа. Каждый ответ — это одно решение, люди будут голосовать за то, что, по их мнению, лучше для сообщества. Таким образом, я буду вознагражден, если мой ответ будет полезен. Вы все еще можете пометить свой ответ как тот, который вы предпочитаете. Я все равно отредактировал и проголосовал за ваш ответ, так как он работает и является отличным ответом для людей, которым абсолютно необходимо использовать setuptool!

Dorian Turba 30.01.2023 16:49

Другие вопросы по теме