[英]I can't seem to get --py-files on Spark to work
我在 Spark 上使用 Python 時遇到問題。 我的應用程序有一些依賴項,例如 numpy、pandas、astropy 等。我不能使用 virtualenv 創建具有所有依賴項的環境,因為除了 HDFS 之外,集群上的節點沒有任何公共掛載點或文件系統。 因此我堅持使用spark-submit --py-files
。 我將站點包的內容打包在一個 ZIP 文件中,並像使用--py-files=dependencies.zip
選項一樣提交作業(如在 Spark 執行程序節點上安裝 Python 依賴項的最簡單方法中所建議的那樣? )。 但是,集群上的節點似乎仍然沒有看到內部的模塊,並且在導入 numpy 時會拋出諸如此類的ImportError
。
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 shell 時,一切正常,因此依賴項都在那里。 有誰知道,可能導致此問題的原因以及如何解決?
謝謝!
首先,我假設您的依賴項列在requirements.txt
。 要打包和壓縮依賴項,請在命令行中運行以下命令:
pip install -t dependencies -r requirements.txt
cd dependencies
zip -r ../dependencies.zip .
上面, cd dependencies
命令對於確保模塊位於 zip 文件的頂層至關重要。 感謝Dan Corin 的提醒。
接下來,通過以下方式提交作業:
spark-submit --py-files dependencies.zip spark_job.py
--py-files
指令將 zip 文件發送給 Spark 工作人員,但沒有將其添加到PYTHONPATH
(讓我感到困惑的根源)。 要將依賴項添加到PYTHONPATH
以修復ImportError
,請將以下行添加到 Spark 作業spark_job.py
:
sc.addPyFile("dependencies.zip")
任何使用商品硬件進行分布式計算的人都必須假設底層硬件可能是異構的。 由於需要 C 編譯,因此在客戶端機器上構建的 Python egg 將特定於客戶端的 CPU 架構。 為 NumPy、SciPy 或 Pandas 等復雜的編譯包分發雞蛋是一種脆弱的解決方案,可能在大多數集群上失敗,至少最終是這樣。
雖然上面的解決方案沒有構建一個雞蛋,但同樣的准則也適用。
首先,您需要通過--py-files或--files傳遞文件
現在在您的代碼中,使用以下命令添加這些 zip/文件
sc.addPyFile("your zip/file")
現在使用如下別名在代碼中導入您的 zip/文件以開始引用它
import zip/file as your-alias
注意:導入時不需要使用文件擴展名,如末尾的.py
希望這是有用的。
為了讓這種依賴分布方法與編譯擴展一起工作,我們需要做兩件事:
使用以下腳本創建依賴項 zip 將確保您與系統上已安裝的任何軟件包隔離。 這是假設的virtualenv安裝並requirements.txt
當前目錄中存在,並輸出dependencies.zip
與所有的依賴在根級別。
env_name=temp_env
# create the virtual env
virtualenv --python=$(which python3) --clear /tmp/${env_name}
# activate the virtual env
source /tmp/${env_name}/bin/activate
# download and install dependencies
pip install -r requirements.txt
# package the dependencies in dependencies.zip. the cd magic works around the fact that you can't specify a base dir to zip
(cd /tmp/${env_name}/lib/python*/site-packages/ && zip -r - *) > dependencies.zip
現在可以像這樣部署、解壓縮和包含在 PYTHONPATH 中的依賴項
spark-submit \
--master yarn \
--deploy-mode cluster \
--conf 'spark.yarn.dist.archives=dependencies.zip#deps' \
--conf 'spark.yarn.appMasterEnv.PYTHONPATH=deps' \
--conf 'spark.executorEnv.PYTHONPATH=deps' \
.
.
.
spark.yarn.dist.archives=dependencies.zip#deps
分發您的 zip 文件並將其解壓縮到名為deps
的目錄
spark.yarn.appMasterEnv.PYTHONPATH=deps
spark.executorEnv.PYTHONPATH=deps
在 PYTHONPATH 中為 master 和所有 worker 包含deps
目錄
--deploy-mode 集群
在集群上運行主執行程序,以便它獲取依賴項
您可以找到您需要的所有 .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
Spark 也會默默地無法加載使用 python zipfile
模塊創建的 zip 存檔。 必須使用 zip 實用程序創建 Zip 存檔。
嘗試使用--archives
將您的 anaconda 目錄存檔到每個服務器,並使用--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=
告訴您的--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=
服務器您的 anaconda 目錄中的 python 執行程序路徑在哪里。
我們的完整配置是這樣的:
--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=./ANACONDA/anaconda-dependencies/bin/python
--archives <S3-path>/anaconda-dependencies.zip#ANACONDA
正如 Andrej Palicka 在評論中解釋的那樣,
“問題在於,Python 無法從 .zip 文件(docs.python.org/2/library/zipimport.html)導入 .so 模塊”。
我發現的一個解決方案是將非 .py 文件一一添加到由逗號分隔的 py 文件中:
spark-submit --py-files modules/toolbox.cpython-38-x86_64-linux-gnu.so,modules/product.cpython-38-x86_64-linux-gnu.so spark_fro
m_cython.py
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.