有没有一种方法可以强制Spark工作者使用分布式numpy版本而不是其上安装的版本?

时间:2018-12-16 16:03:57

标签: pandas apache-spark pyspark pyarrow

情况如下:在使用Spark 2.3的企业集群上,我想运行pandas_udf,它要求pyarrow,而numpy需要numpy 0.14(AFAIK)。 能够分发pyarrow(我认为无法对此100%进行验证):

 pyspark.sql.SparkSession.builder.appName("pandas_udf_poc").config("spark.executor.instances","2")\
                                              .config("spark.executor.memory","8g")\
                                              .config("spark.driver.memory","8g")\
                                              .config("spark.driver.maxResultSize","8g")\
                                              .config("py-files", "pyarrow_depnd.zip")\
                                              .getOrCreate()  

spark.sparkContext.addPyFile("pyarrow_depnd.zip")

zip是将pip安装到dir并将其压缩的结果。

但是pyarrow不能与节点numpy 0.13一起使用,我想我可以尝试向所有节点分发一个完整的env,但是我的问题是,有没有一种方法可以避免这种情况并使该节点使用一个不同的numpy(已经在pyarrow zip中分发了

谢谢

1 个答案:

答案 0 :(得分:0)

最后,不必使用虚拟环境,但是无法避免将python的完整副本(包含所需的依赖项)分发给所有节点。

首先构建了python的完整副本(使用了conda env,但是您可能可以使用其他方式):

conda create --prefix /home/me/env_conda_for_pyarrow
source activate /home/me/env_conda_for_pyarrow
conda install numpy 
conda install pyarrow

在这种情况下,必须先安装conda-forge频道,然后才能进行安装,以获取最新版本。

第二,压缩发行版:

zip -r env_conda_for_pyarrow.zip env_conda_for_pyarrow

然后使用档案文件分发zip文件,并使用env变量PYSPARK_PYTHON指向它:

import os, sys
os.environ['PYSPARK_PYTHON']="dist_python/env_conda_for_pyarrow/bin/python"

import pyspark
spark = \
pyspark.sql.SparkSession.builder.appName("pysaprk_python")\
.config("spark.yarn.dist.archives", "env_conda_for_pyarrow.zip#dist_python")\
.getOrCreate()

print spark.version, spark.sparkContext.master

就这样,完成了。这是我用于测试的一些脚本:

def list_nodes_dir(x): # hack to see workers file dirs
    import os
    return os.listdir('dist_python')

spark.sparkContext.parallelize(range(1), 1).map(list_nodes_dir).collect()    



def npv(x): # hack to see workers numpy version
    import numpy as np
    return np.__version__

set(spark.sparkContext.parallelize(range(10), 10).map(npv).collect())



# spark documents example
from pyspark.sql.functions import pandas_udf, PandasUDFType
from pyspark.sql.types import IntegerType, StringType
slen = pandas_udf(lambda s: s.str.len(), IntegerType())  

@pandas_udf(StringType())  
def to_upper(s):
    return s.str.upper()

@pandas_udf("integer", PandasUDFType.SCALAR)  
def add_one(x):
    return x + 1

df = spark.createDataFrame([(1, "John Doe", 21)], ("id", "name", "age"))  
df.select(slen("name").alias("slen(name)"), to_upper("name"), 
add_one("age")).show()