У нас есть репозиторий pyspark-jobs, который содержит zip-артефакты в S3 после того, как процесс сборки помещает их туда. Предположим, что одной из таких задач является find-homes.zip
, содержание которой показано ниже:
find-homes.zip
+-find_homes
+- __init__.py
+- run.py
+-helpers
+- __init__.py
+- helper_mod.py
Мне нужно выполнить run.py
(который зависит от помощников) внутри zip как основной. Я запускаю задание в режиме клиента, и я попробовал команду spark-submit --py-files find-homes.zip find_homes.run.py
. Файл find_homes.run.py
представляет собой тонкую оболочку, содержащую следующий код:
import os
import importlib
def main():
filename = os.path.basename(__file__)
module = os.path.splitext(filename)[0]
module = importlib.import_module(module)
module.main()
if __name__ == '__main__':
main()
В основном я следую предложению из ветки это SO, но ничего не работает. Ошибка, которую он показывает после запуска задания:
Traceback (most recent call last):
File "/home/hadoop/find_homes.run.py", line 13, in <module>
main()
File "/home/hadoop/find_homes.run.py", line 8, in main
module = importlib.import_module(module)
File "/usr/lib64/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 941, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'find_homes'
Я теряю терпение, пытаясь понять, чего мне здесь не хватает. Ни одно из предложений (включая обновление PYTHONPATH с расположением zip) не работает, поэтому любая помощь или даже подталкивание в правильном направлении очень ценятся. Я использую EMR v5.23.0
против Spark 2.4
Обновлять
Что ж, случилось что-то странное. Я использовал следующую задачу градиента для создания почтового индекса:
task build(type: Zip) {
from ('src/')
into "."
archiveName = "${project.name}.zip"
includeEmptyDirs = false
destinationDir new File(projectDir, 'build/distributions')
}
Я не знаю, как мне это пришло в голову, но я просто разархивировал свой артефакт и снова заархивировал его с помощью zip -r find_homes.zip <packages>
, а затем использовал полученный zip с помощью spark-submit, и это сработало. Не знаю, почему, поскольку структуры папок в обоих случаях одинаковы.
Для тех, кто использует EMR для искровых заданий, я делюсь своими выводами и маршрутом, который я выбрал, опробовав разные подходы. Ключевые моменты представлены в таблице ниже.
Управляйте зависимостями Python с помощью скрипта начальной загрузки EMR. Все пакеты Python, от которых у вас есть зависимости, должны быть установлены на исполнителях (например, pandas, sklearn и т. д.). Это можно сделать через этот загрузочный скрипт в момент запуска кластера.
Предполагая, что у вас есть проект gradle для Python (возможно, вместе с другими языками, такими как Java), pygradle, похоже, не добавляет такой большой ценности, если позаботиться о случае использования № 1.
Встроенная задача gradle zip вряд ли подойдет для создания zip-файла с вашими модулями Python. Я добавил модуль создания zip с помощью Python и вызвал его в задаче gradle через выполнение из командной строки. Итак, задача gradle вызывает скрипт Python с соответствующими аргументами для создания zip-файла. Убедитесь, что ваши пакеты присутствуют на корневом уровне zip. Затем перейдите по ссылке, которой я поделился в вопросе выше, чтобы отправить задание pyspark.