Я использую Docker в сочетании с virtualenv для запуска проекта для клиента, но получаю сообщение об ошибке ModuleNotFound для sklearn.
В моем Pipfile я добавил зависимость numpy
numpy = "==1.21.6"
Ошибка вылетает из следующей строки
np.load(PATH_TO_NPY_FILE, allow_pickle=True)
со следующей трассировкой стека:
development_1 | File "/root/.local/share/virtualenvs/code-_Py8Si6I/lib/python3.7/site-packages/numpy/lib/npyio.py", line 441, in load
development_1 | pickle_kwargs=pickle_kwargs)
development_1 | File "/root/.local/share/virtualenvs/code-_Py8Si6I/lib/python3.7/site-packages/numpy/lib/format.py", line 748, in read_array
development_1 | array = pickle.load(fp, **pickle_kwargs)
development_1 | ModuleNotFoundError: No module named 'sklearn'
Я нахожу это странным, потому что sklearn
должен быть установлен как часть дерева зависимостей numpy, верно?
Тем не менее, я попробовал предложения, которые я нашел в других сообщениях, например, добавление следующей команды явно в мой Dockerfile
python -m pip install scikit-learn scipy matplotlib
Однако ошибка по-прежнему сохраняется.
Для полноты я предоставлю дополнительную информацию ниже, хотя ключевой вопрос остается, почему установка numpy не подразумевает наличия его подзависимостей.
Структура проекта
Проект является своеобразным мостом между SQS с одной стороны и логикой клиента с другой. Код, из которого возникает ошибка, исходит из подмодуля git, а Pipfile добавляется в репозиторий верхнего уровня. Подмодуль не содержит Pipfile. В папке submodules есть файл __init__.py
, потому что он содержит функции, которые я хочу использовать в своем коде src.
В дереве ниже мой код находится в main.py
, а код выдачи ошибки — в submodules/module2/bar.py
.
|- src/
| |- main.py
|
|- submodules/
| |- module1
| | |- foo.py
| | |- setup.py
| |
| |- module2
| | |- bar.py
| |
| |- __init__.py
|
|- .gitmodules
|- Pipfile
|- Dockerfile
Содержимое Dockerfile
Обратите внимание, что на данный момент это своего рода совокупность решений, которые я взял из другого поста по этому вопросу. Вот почему в настоящее время включены как pip install scikit-learn
, так и apt-get install python3-sklearn
. Обрежу позже, когда наконец решу эту проблему.
FROM python:3.7
WORKDIR code/
COPY Pipfile .
COPY submodules/ submodules/
RUN pip install pipenv && \
pipenv install --deploy && \
python -m pip install scikit-learn scipy matplotlib && \
apt-get update && \
apt-get install -y locales ffmpeg libsm6 libxext6 libxrender-dev python3-sklearn && \
sed -i -e 's/# nl_BE.UTF-8 UTF-8/nl_BE.UTF-8 UTF-8/' /etc/locale.gen && \
dpkg-reconfigure --frontend=noninteractive locales
ENV LANG nl_BE.UTF-8
ENV LC_ALL nl_BE.UTF-8
COPY .env .
COPY src/ .
COPY data/ data
CMD [ "pipenv", "run", "python", "main.py" ]x
Содержимое пип-файла
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
python-dotenv = "*"
boto3 = "*"
pySqsListener = "*"
xpress = "==9.0.5"
module1 = {path = "./submodules/module1"}
pandas = "==1.3.4"
numpy = "==1.21.6"
[dev-packages]
[requires]
python_version = "3.7"
Я нахожу это странным, потому что sklearn должен быть установлен как часть дерева зависимостей numpy, верно?
Нет, scikit-learn
не зависит от numpy (наоборот).
Поскольку для загрузки этого файла рассола требуется sklearn
, просто поместите scikit-learn
в pipfile (и matplotlib
, если вам это нужно); это зависимость вашего проекта.
Установка их за пределами pipenv
-сгенерированной среды с этим python -m pip install scikit-learn scipy matplotlib
, скорее всего, не будет иметь никакого эффекта (как и apt-installed python3-sklearn
), поскольку виртуальные окружения спроектированы так, чтобы быть отделенными от окружающей среды.
Исключение фактически возникает внутри pickle.load()
(которое вызывается numpy.load()
), когда встроенный механизм десериализации Python пытается десериализовать что-то, что ссылается на sklearn
. Но да, рад, что смог помочь!
Ах, тогда я, должно быть, ошибся насчет того, что зависит от чего. Я основывал свое предположение на трассировке стека, вызывающей ModuleNotFoundError из папки numpy. Также кажется, что вторая часть вашего ответа имеет смысл, и добавление ее в Pipfile действительно устраняет ошибку. Спасибо