pyspark 中使用集群未安装的python三方库:加载虚拟python环境

简介

  在使用pyspark运行python代码的过程中,通常遇到集群环境中没有相应的python三方库,即:ImportError: No module named ** ,对于该种情况,通常有两种解决方案:
 1. 集群中的python环境安装相应的三方库! 走流程、找运维,贼麻烦
 2. 集群未配置python环境,加载虚拟python环境!(重点讲解该方式,用起来贼方便)

未加载库的通常处理方式

  使用pyspark过程中,遇到没有相应python库,可以通常有三种处理方法:
 1.单一py文件
  spark-submit命令中添加 --py-files a.py 即可:

spark-submit \
    --master yarn \
    --deploy-mode cluster \
    --num-executors 40 \
    --queue default \
    --verbose \
    --py-files a.py  \
    b.py 

 2.自建模块或python简单三方库(不含.so文件, 如 jieba)
  直接将python相应的模块如(jieba包)打包为zip,然后spark-submit命令中动态加载该模块即可;(本人直接将windows下python环境中site-packages 中的jieba 打包为zip, 然后使用如下提交命令就可以直接使用,注意模块的依赖包)
  注意点:
    1.模块存在依赖包
    2.zip 包文件较大可以先将zip包上传到HDFS中
    3.当有多个模块需要引用时,可以使用逗号分隔

spark-submit \
    --master yarn \
    --deploy-mode cluster \
    --num-executors 40 \
    --queue default \
    --verbose \
    --py-files hdfs://xxx/jieba.zip  \
    b.py 

 3.python复杂三方库(含.so 文件,即动态加载库,如numpy、pandas)(本文重点讲解该方法

加载虚拟环境

 1.在任意台机器上安装Anaconda 软件

 2.通过Anaconda 创建虚拟Python环境

(尝试过使用virtualenvwrapper 创建虚拟环境,但是在应用时失败了,建议直接使用Anaconda,具体原因见文末)

 3.在创建好的Python环境中安装依赖的Python包

 4.将整个虚拟Python环境打包为zip,或tar.gz包
进入到虚拟环境下,如/home/hadoop/anaconda3/envs,使用以下命令将虚拟环境进行打包

zip -r conda_env.zip conda_env	  # 虚拟环境为conda_env, 打包为conda_env.zip 文件

 5.提交Pyspark Application,通过 --archives 选项指定 zip 包路径(可以将虚拟环境zip上传到HDFS或某个节点下 ),然后是在cluster、client模式下提交application,示例如下

spark-submit 提交application时主要是添加如下三行conf,对于cluster与client存在差异
--conf spark.yarn.dist.archives=/wang/code/conda_env \
--conf spark.pyspark.driver.python=/wang/code/conda_env/bin/python \
--conf spark.pyspark.python=/wang/code/conda_env/bin/python \

######################## cluster模式
spark-submit \
    --master yarn \
    --deploy-mode cluster \
    --num-executors 50 \
    --queue default \
    --verbose \
    --conf spark.yarn.dist.archives=hdfs:wang/conda_env.zip#python36 \
    --conf spark.pyspark.driver.python=./python36/conda_env/bin/python \
    --conf spark.pyspark.python=./python36/conda_env/bin/python \
    test.py 
注意:
	1、hdfs:/// 是三条斜杠,之前参考其他资料写的两条斜杠一直报错
	2、archives 命令后的 # 是必须的(通常会以为是注释),它指的是将 zip包 临时解压到的文件夹,后续两条--conf命令直接引用该文件夹即可
    3、在提交 Pyspark Application 时会将该环境 zip 包上传到运行Application 的所在的每个节点上,并解压缩为Python 代码提供运行环境,如果不想每次都从客户端将该环境文件上传到集群中运行 pyspark application 的节点上,可以采用zip 包上传到HDFS的方式即可

######################## client模式
spark-submit \
    --master yarn \
    --deploy-mode client \
    --driver-memory 2g \
    --num-executors 50 \
    --queue default \
    --verbose \
    --conf spark.yarn.dist.archives=hdfs:wang/conda_env.zip#python36 \
    --conf spark.pyspark.driver.python=/mnt/wang/conda_env/bin/python \
    --conf spark.pyspark.python=./python36/conda_env/bin/python \
    test.py
注意:
	1、与cluster主要不同在  --conf spark.pyspark.driver.python
	对应的路径为提交application 的节点上解压conda_env.zip 后对应的/bin/python路径,即conda_env.zip 解压后的路径为/mnt/wang/conda_env/ ,然后再加上对应的路径下的 /bin/python,其目的就是集群 driver节点使用的python环境

补充:为什么使用virtualenv创建的虚拟环境无法作为python环境应用到Pyspark任务中??
归其主要原因还是在于:virtualenv本质上并不能真正隔离系统的python环境和自身虚拟环境的python环境,即使用virtualenv创建的虚拟环境与系统的python环境仍然存在关联,具体可以在virtualenv创建的虚拟环境中测试以下代码

import sys, json, _json
print(sys.path)
print(json.__file__)
print(_json.__name__)

在这个例子中,我们创建了一个虚拟环境 t2 ,并尝试在虚拟环境 import Python 自带的 json 模块,结果发现引用的模块地址事实上是操作系统而不是虚拟环境的。

从 sys.path 的结果可以看到,虚拟环境中的 Python import 模块时会尝试先从虚拟环境中的 Python PATH 搜索,然后会尝试从系统的 Python PATH 搜索。如果 import 的模块二次引用其他的 Python 模块实现,则可能导致系统的 Python 模块和虚拟环境中的 Python 模块交叉使用的情况。

在上面的例子中,可以看到 json 模块和实现其部分功能的 _json 模块分别属于系统和虚拟环境。如果系统和虚拟环境中的 Python 版本、模块版本不一致,则很容易导致服务出现问题,并且最重导致 Python 进程本身崩溃,并且很难调试、查找原因。

virtualenv 打包方案从原理上并不可靠

参考

https://blog.csdn.net/weixin_41002327/article/details/112252163
https://blog.csdn.net/yawei_liu1688/article/details/112304595.

你可能感兴趣的:(spark,数据挖掘,spark,python,数据挖掘)