在spark上运行Python脚本遇到“ImportError: No module name xxxx”

在spark上运行Python脚本遇到“ImportError: No module name xxxx”

这是因为运行Python脚本的集群上的Python环境里缺乏脚本运行需要的依赖。

根据所需依赖的不同性质可以分为3类:

(1)单个的*.py或者*.py[co]

(2)自建模块

(3)自包含的依赖项

(4)复杂依赖

【1】只依赖于单个文件(only depend on a sigle file)

(1)可以通过使用spark-submit命令中的—py-files选项并指定文件的本地路径,将依赖文件提供给所有的执行程序。

/opt/spark/bin/spark-submit --master yarn-cluster --py-files dependency.py my_script.py

(2)使用sc.addPyFiles(path)函数(文件路径作为参数)以编程的方式将所需文件添加到SparkContext。

sc = SparkContext(master=”yarn-cluster”,appName=”myApp”)

sc.addPyFile(file_path)

【2】自建模块

比如在Python脚本中使用了

from model.file import *

那么就需要将model文件夹进行打包。注意打包指令要在文件所在的父目录下进行。比如文件夹model的路径为/home/workspace/model,那么就要保证打包命令是在/home/workspace/下进行的,但这样打包会将workspace文件夹下的文件全部打包。

zip -r ../my_dependencies.zip .

备注:这样操作的原因是,要确保所需文件在*.zip的顶层(ensure that the modules are the in the top level of the zip file),即当解压缩deps.zip时,文件和文件夹必须出现在顶层。当在spark中执行任务时,相关的依赖包会以如下方式进行查找:

/hadoopdir3/yarn/…/my_dependencies.zip/model/file/__init__.py

两种打包命令的区别:

正确的:

$ zip -r ../deps.zip .
adding: __init__.py (stored 0%)
adding: _markerlib/ (stored 0%)
adding: _markerlib/__init__.py (deflated 55%)
adding: _markerlib/__init__.pyc (deflated 60%)
adding: _markerlib/markers.py (deflated 63%)
adding: _markerlib/markers.pyc (deflated 61%)
adding: aniso8601/ (stored 0%)
...

错误的:

$ zip -r deps.zip folder_name/*
adding: folder_name/__init__.py (stored 0%)
adding: folder_name/_markerlib/ (stored 0%)
adding: folder_name/_markerlib/__init__.py (deflated 55%)
adding: folder_name/_markerlib/__init__.pyc (deflated 60%)
adding: folder_name/_markerlib/markers.py (deflated 63%)
adding: folder_name/_markerlib/markers.pyc (deflated 61%)
adding: folder_name/aniso8601/ (stored 0%)

...

 

打包好之后,就可以按照【1】中分发单个文件给集群的方法将*.zip文件分发给集群。

/opt/spark/bin/spark-submit --master yarn-cluster --py-files my_dependency.zip my_script.py

或者

sc = SparkContext(master=”yarn-cluster”,appName=”myApp”)

sc.addPyFile(file_path)

【3】自包含的依赖项(a self contained module (meaning a module with no other dependencies))

如果所需依赖是Python的第三方模块,可以通过virtualenv创建一个独立的Python运行环境,然后在这个Python运行环境里安装各种第三方包。然后将安装的第三方包打包成*.zip或者*.egg。

详细步骤如下:

第一步,用pip安装virtualenv

# Python2版本

pip2 install virtualenv

# Python3版本

pip3 install virtualenv

第二步,创建一个独立的Python运行环境,命名为pyspark-env

virtual –no-site-packages pyspark-env

# --no-site-packages,可以使已经安装的系统Python环境中的所有第三方包不会复制过来,这样可以得到一个不带任何第三方包的“干净的”的Python运行环境。

第三步,用source进入该环境

source pyspark-env/bin/activate

# 使用deactivate 命令退出当前env环境

deactivate

可以发现,命令提示符变了,有个pyspark-env前缀,表示当前环境使一个名为pyspark-env的Python环境。

第四步,正常安装各种第三方包

pip install numpy

在pyspark-env环境下,用pip安装的包都被安装到pyspark-env这个环境下,系统Python环境不受任何影响。

第五步,打包安装的第三方包

所有的第三方的包都会被pip安装到lib/python2/site-packages目录下面。

进入site-packages目录下面,

cd ./lib/python2.7/site-packages

zip -r /zip-path/my_dependencies.zip 

.同样也要注意,必须在所需包的父目录下进行打包,使文件和文件夹作为*.zip的顶层文件。

打包好之后,就可以通过

spark-submit –master yarn-cluster –py-files my_dependency.zip my_script.py

或者通过在脚本中sparkcontext的属性添加

sc.addfiles(“path/my_dependency.zip”)

将依赖库分发到各节点。

警告:如果您的软件包依赖于已编译的代码,并且您的集群中的计算机具有与您编译egg的代码不同的CPU体系结构,则这将不起作用。

比如Numpy,通过这种方式没有解决依赖的问题,最后是让集群管理员直接在集群上安装了Numpy。

主要原因是Python不允许动态导入.so文件,而Numpy由于是C编译的,存在*.so文件。

 

【4】复杂依赖(Complex Dependency)

要用的包依赖于其他的依赖项

比如Pandas依赖于NumPy和SciPy,以及其他包。

理论上,我们可以为所需的依赖包创建一个*.egg文件,然后通过命令行的—py-files选项,或者sc.addPyFiles()方法 将依赖文件传送给执行器。

但是对于复杂依赖,这种方法很脆弱:

A Python egg built on a client machine will be specific to the client’s CPU architecture because of the required C compilation. Distributing an egg for a complex, compiled package like NumPy, SciPy, or pandas is a brittle solution that is likely to fail on most clusters, at least eventually.

 

参考:

https://stackoverflow.com/questions/29495435/easiest-way-to-install-python-dependencies-on-spark-executor-nodes

https://stackoverflow.com/questions/35214231/importerror-no-module-named-numpy-on-spark-workers

https://www.cloudera.com/documentation/enterprise/5-5-x/topics/spark_python.html

https://blog.cloudera.com/blog/2015/09/how-to-prepare-your-apache-hadoop-cluster-for-pyspark-jobs/

https://stackoverflow.com/questions/36461054/i-cant-seem-to-get-py-files-on-spark-to-work

http://blog.danielcorin.com/code/2015/11/10/pyspark.html

 

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
本项目经测试过,真实可靠,请放心下载学习。这两个技术在大数据处理和Java Web开发中扮演着重要的角色。在此次总结中,我将回顾我所学到的内容、遇到的挑战和取得的进展。 首先,我开始了对Spark的学习。Spark是一个强大的分布式计算框架,用于处理大规模数据集。通过学习Spark,我了解了其基本概念和核心组件,如RDD(弹性分布式数据集)、Spark SQL、Spark Streaming和MLlib等。我学会了使用Spark编写分布式的数据处理程序,并通过调优技巧提高了程序的性能。在实践过程中,我遇到了一些挑战,比如调试复杂的数据流转和处理逻辑,但通过查阅文档和与同学的讨论,我成功地克服了这些困难。最终,我能够使用Spark处理大规模数据集,并通过并行化和分布式计算加速任务的执行。 其次,我开始了对Spring Boot的学习。Spring Boot是一种快速构建基于Spring框架的应用程序的方式。通过学习Spring Boot,我了解了其核心思想和基本原理,以及如何构建RESTful Web服务、使用数据库、进行事务管理等。我学会了使用Spring Boot快速搭建Java Web应用程序,并且能够运用Spring Boot的特性来简化开发流程。在学习的过程中,我遇到了一些挑战,比如配置文件的理解和注解的正确使用,但通过查阅官方文档和阅读相关书籍,我逐渐解决了这些问题。最终,我能够独立地使用Spring Boot开发Web应用程序,并运用其优秀的特性提高了开发效率。 总结来说,本学期我在Spark和Spring Boot方面取得了一定的进展。通过学习Spark,我掌握了分布式数据处理的基本原理和技巧,并通过实践应用到了大规模数据集的处理中。通过学习Spring Boot,我了解了现代化的Java Web开发方式,并通过实践构建了一些简单的Web应用程序。我还意识到在学习过程中遇到的困难和挑战是正常的,通过不断的努力和学习,我能够克服这些困难并取得进步。 在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的技术和框架,以便能够适应不同的项目需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值