在Spark执行器节点上安装Python依赖项的最简单方法?

时间:2015-04-07 15:35:07

标签: hadoop dependencies apache-spark shared-libraries distributed-computing

据我所知,您可以使用Python Spark程序将各个文件作为依赖项发送。但是完全成熟的图书馆(例如numpy)呢?

Spark是否有办法使用提供的包管理器(例如pip)来安装库依赖项?或者这是否必须在执行Spark程序之前手动完成?

如果答案是手动的,那么在大量分布式节点上同步库(安装路径,版本等)的“最佳实践”方法是什么?

1 个答案:

答案 0 :(得分:19)

实际上已经尝试过,我认为我发布的评论链接并没有完全符合你想要的依赖关系。你非常合理地要求的是一种方法,让Spark可以很好地使用setuptools和pip来安装依赖项。我觉得Spark不能更好地支持这一点。第三方依赖问题在很大程度上是通用Python解决的,但在Spark下,似乎假设你会回到手动依赖管理或其他什么。

我一直在使用基于virtualenv的不完善但功能强大的管道。基本理念是

  1. 仅为您的Spark节点创建virtualenv
  2. 每次运行Spark作业时,都要运行所有内部Python库的新foreach (var item in db.Pos.GroupBy(a=> a.Pla).Select(p=> new {Pdv = p.Pdv, Pla = p.Key, Nombre=p.Descripcion, Rid=p.Rid, Quantity = p.Sum(q=>q.Cantidad), Total= p.Sum(x=>x.Total)})) { listItemPopu.Add(item.ToString()); } 。如果您使用pip install进行了设置,则会安装其依赖项
  3. 压缩virtualenv的site-packages目录。这将包括您的库及其依赖项,工作节点将需要它们,但不包括它们已有的标准Python库
  4. 将包含您的库及其依赖项的单个setuptools文件作为参数传递给.zip
  5. 当然,您需要编写一些帮助程序脚本来管理此过程。这是一个改编自我一直使用的辅助脚本,无疑可以改进很多:

    --py-files

    我有一系列其他简单的包装程序脚本,我运行它来提交我的spark作业。我只是首先调用此脚本作为该过程的一部分,并确保在运行#!/usr/bin/env bash # helper script to fulfil Spark's python packaging requirements. # Installs everything in a designated virtualenv, then zips up the virtualenv for using as an the value of # supplied to --py-files argument of `pyspark` or `spark-submit` # First argument should be the top-level virtualenv # Second argument is the zipfile which will be created, and # which you can subsequently supply as the --py-files argument to # spark-submit # Subsequent arguments are all the private packages you wish to install # If these are set up with setuptools, their dependencies will be installed VENV=$1; shift ZIPFILE=$1; shift PACKAGES=$* . $VENV/bin/activate for pkg in $PACKAGES; do pip install --upgrade $pkg done TMPZIP="$TMPDIR/$RANDOM.zip" # abs path. Use random number to avoid clashes with other processes ( cd "$VENV/lib/python2.7/site-packages" && zip -q -r $TMPZIP . ) mv $TMPZIP $ZIPFILE 时将第二个参数(zip文件的名称)作为--py-files参数传递(如注释中所述) )。我总是运行这些脚本,所以我永远不会意外地运行旧代码。与Spark开销相比,我的小规模项目的包装开销很小。

    可以进行大量改进 - 例如,知道何时创建新的zip文件,将其拆分为两个zip文件,一个包含经常更改的私有包,另一个包含很少更改的依赖项,这些都是需要经常重建。在重建zip之前,您可以更聪明地检查文件更改。检查参数的有效性也是一个好主意。但是现在这足以满足我的目的。

    我提出的解决方案并非专为NumPy这样的大规模依赖项而设计(尽管它可能适用于它们)。此外,如果要构建基于C的扩展,并且驱动程序节点与群集节点具有不同的体系结构,则它将不起作用。

    我已经在别处看到了在所有节点上运行像Anaconda这样的Python发行版的建议,因为它已经包含了NumPy(和many other packages),这可能是获得NumPy的更好方法正如其他基于C的扩展一样。无论如何,我们不能总是期望Anaconda在正确的版本中拥有我们想要的PyPI包,此外你可能无法控制你的Spark环境以便能够将Anaconda放在它上面,所以我认为这是基于virtualenv的方法仍然有用。