我似乎无法在Spark上使用--py文件来工作

And*_*cka 24 python apache-spark pyspark

我在Spark上使用Python时遇到了问题.我的应用程序有一些依赖项,例如numpy,pandas,astropy等.我不能使用virtualenv来创建一个包含所有依赖项的环境,因为除了HDFS之外,集群上的节点没有任何公共mountpoint或文件系统.因此我坚持使用spark-submit --py-files.我将site-packages的内容打包到一个ZIP文件中并像使用--py-files=dependencies.zip选项一样提交作业(最简单的方法是在Spark执行器节点上安装Python依赖项?).但是,群集上的节点似乎仍然没有看到内部的模块,并且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
Run Code Online (Sandbox Code Playgroud)

当我切换到virtualenv并使用本地pyspark shell时,一切正常,所以依赖都在那里.有谁知道,什么可能导致这个问题,以及如何解决它?

谢谢!

ram*_*ser 53

首先,我假设您的依赖项列在requirements.txt.要打包和压缩依赖项,请在命令行运行以下命令:

pip install -t dependencies -r requirements.txt
cd dependencies
zip -r ../dependencies.zip .
Run Code Online (Sandbox Code Playgroud)

上面,该cd dependencies命令对于确保模块位于zip文件的顶层是至关重要的.感谢Dan Corin的负责人.

接下来,通过以下方式提交作业

spark-submit --py-files dependencies.zip spark_job.py
Run Code Online (Sandbox Code Playgroud)

--py-files指令将zip文件发送给Spark工作者,但不会将其添加到PYTHONPATH(我的混淆源).要将依赖项添加到PYTHONPATH要修复的位置ImportError,请将以下行添加到Spark作业中spark_job.py:

sc.addPyFile("dependencies.zip")
Run Code Online (Sandbox Code Playgroud)

Cloudera帖子的一个警告:

假设任何使用商用硬件进行分布式计算的人必须假设底层硬件可能是异构的.由于所需的C编译,在客户端计算机上构建的Python egg将特定于客户端的CPU体系结构.为像NumPy,SciPy或pandas这样复杂的编译软件包分配一个鸡蛋是一个脆弱的解决方案,它可能在大多数集群上失败,至少最终会失败.

虽然上述解决方案不能制作鸡蛋,但同样的准则也适用.

  • 据我所知,我试图运行的集群是同质的.主要问题是Python不允许动态导入`.so`文件,尽管Spark有可能以某种方式克服了这一点.我会试一试,然后再回复你. (3认同)
  • “ --py-files”没有将其添加到“ PYTHONPATH”中,这不仅使您感到困惑,而且这似乎是一个普遍的问题! (3认同)
  • 有没有人能够在此期间找到解决方案来导入Spark中具有.so文件的依赖项?谢谢 (2认同)
  • 在我在网上找到的针对此问题的所有可能解决方案中,这是最好的。尽管如此,这感觉就像是黑客攻击。他们真的应该为 python 依赖项发布一个类似于 `--packages` 的选项! (2认同)

小智 14

  • 首先,您需要通过--py-files--files传递文件

    • 当您使用上述标志传递zip /文件时,基本上您的资源将被转移到HDFS上创建的临时目录,仅用于该应用程序的生命周期.
  • 现在,在您的代码中,使用以下命令添加这些zip /文件

    sc.addPyFile("your zip/file")

    • 以上是什么,它将文件加载到执行环境,如JVM.
  • 现在,使用如下所示的别名导入您的代码中的zip /文件,以开始引用它

    import zip/file as your-alias

    注意:您不需要使用的文件扩展名,同时引进,像的.py

希望这很有用.

  • 我写这可能是为时已晚,但可能对某人有所帮助.您尝试导入的模块(文件夹)必须有一个名为`__init __.py`的空白文件,否则此设置将无效.这个答案中的其他一切都和它的赞成数一样完美. (4认同)

Dim*_*ima 6

为了让这种依赖分布方法与编译扩展一起工作,我们需要做两件事:

  1. 在与目标集群相同的操作系统上运行 pip install(最好在集群的主节点上)。这可确保兼容的二进制文件包含在您的 zip 中。
  2. 在目标节点上解压缩您的存档。这是必要的,因为 Python 不会从 zip 文件导入已编译的扩展。( https://docs.python.org/3.8/library/zipimport.html )

使用以下脚本创建依赖项 zip 将确保您与系统上已安装的任何软件包隔离。这假设 virtualenv 已安装requirements.txt并存在于您的当前目录中,并dependencies.zip在根级别输出包含所有依赖项的a 。

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
Run Code Online (Sandbox Code Playgroud)

现在可以像这样部署、解压缩和包含在 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' \
.
.
.
Run Code Online (Sandbox Code Playgroud)

spark.yarn.dist.archives=dependencies.zip#deps
分发您的 zip 文件并将其解压缩到名为deps

spark.yarn.appMasterEnv.PYTHONPATH = DEPS
spark.executorEnv.PYTHONPATH = DEPS
包括deps用于主站与所有工人PYTHONPATH目录

--deploy-mode cluster
集群上运行主执行程序,以便它获取依赖项