Кажется, я не могу получить -py файлы на Spark для работы
У меня проблема с использованием Python на Spark. Мое приложение имеет некоторые зависимости, такие как numpy, pandas, astropy и т.д. Я не могу использовать virtualenv для создания среды со всеми зависимостями, поскольку узлы в кластере не имеют общей точки монтирования или файловой системы, кроме HDFS. Поэтому я застрял с использованием spark-submit --py-files
. Я упаковываю содержимое сайтов-пакетов в ZIP файл и отправляю задание, например, с помощью параметра --py-files=dependencies.zip
(как это предлагается в разделе Самый простой способ установить зависимости Python на узлы-исполнители Spark?). Тем не менее, узлы в кластере по-прежнему не видят модули внутри, и они бросают ImportError
например, при импорте numpy.
File "/path/anonymized/module.py", line 6, in <module>
import numpy
File "/tmp/pip-build-4fjFLQ/numpy/numpy/__init__.py", line 180, in <module>
File "/tmp/pip-build-4fjFLQ/numpy/numpy/add_newdocs.py", line 13, in <module>
File "/tmp/pip-build-4fjFLQ/numpy/numpy/lib/__init__.py", line 8, in <module>
#
File "/tmp/pip-build-4fjFLQ/numpy/numpy/lib/type_check.py", line 11, in <module>
File "/tmp/pip-build-4fjFLQ/numpy/numpy/core/__init__.py", line 14, in <module>
ImportError: cannot import name multiarray
Когда я переключаюсь на virtualenv и использую локальную оболочку pyspark, все работает нормально, поэтому все зависимости есть. Кто-нибудь знает, что может вызвать эту проблему и как ее исправить?
Благодарю!
Ответы
Ответ 1
Во-первых, я буду считать, что ваши зависимости указаны в requirements.txt
. requirements.txt
. Чтобы упаковать и заархивировать зависимости, запустите в командной строке следующее:
pip install -t dependencies -r requirements.txt
cd dependencies
zip -r ../dependencies.zip .
Выше команда cd dependencies
имеет решающее значение для обеспечения того, чтобы модули находились на верхнем уровне zip файла. Спасибо за сообщение Дэна Корина за хедз-ап.
Затем отправьте задание через:
spark-submit --py-files dependencies.zip spark_job.py
--py-files
отправляет zip файл рабочим Spark, но не добавляет его в PYTHONPATH
(источник путаницы для меня). Чтобы добавить зависимости PYTHONPATH
к исправлению ImportError
, добавьте следующую строку в задание spark_job.py
: spark_job.py
:
sc.addPyFile("dependencies.zip")
Оговорка из этого сообщения Клаудера:
Предполагается, что любой, кто делает распределенные вычисления с товарным оборудованием, должен предположить, что базовое оборудование потенциально гетерогенно. Яйцо Python, построенное на клиентской машине, будет специфично для архитектуры процессора клиентов из-за необходимой компиляции C. Распределение яйца для сложного, скомпилированного пакета, такого как NumPy, SciPy или pandas, - это хрупкое решение, которое, по крайней мере, в конечном итоге может потерпеть неудачу на большинстве кластеров.
Хотя вышеприведенное решение не создает яйцо, применяется одно и то же правило.
Ответ 2
-
Сначала вам нужно передать свои файлы через --py файлы или --files
- Когда вы передаете свои zip файлы с указанными выше флагами, в основном ваши ресурсы будут перенесены во временный каталог, созданный на HDFS, только на время жизни этого приложения.
-
Теперь в вашем коде добавьте эти zip файлы, используя следующую команду
sc.addPyFile("your zip/file")
- что делает выше, он загружает файлы в среду выполнения, например JVM.
-
Теперь импортируйте свой zip/файл в свой код с псевдонимом следующим образом, чтобы начать ссылаться на него
import zip/file as your-alias
Примечание. Вам не нужно использовать расширение файла при импорте, например .py в конце
Надеюсь, это полезно.
Ответ 3
Вы можете найти все нужные вам.pys и добавить их относительно. см. здесь для объяснения:
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
# use this if you want to include modules from a subfolder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
# Info:
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
# __file__ fails if script is called in different ways on Windows
# __file__ fails if someone does os.chdir() before
# sys.argv[0] also fails because it doesn't not always contains the path
Ответ 4
Spark также без проблем загрузит zip-архив, созданный с помощью zipfile
модуля python. Zip-архивы должны быть созданы с использованием утилиты zip.