问题描述:
昨天有人使用pyspark遇到一个问题,代码简化为:
1 2 3 4 5 6 7 8 9
| import one from pyspark import SparkConf,SparkContext
conf = SparkConf().setMaster("spark://localhost:7077").setAppName('test') sc = SparkContext(conf=conf) df = sc.textFile("/Users/scut_DELL/data")
print one.count("test") df.map(lambda line: one.count("test"))
|
其中one模块是自己写的在当前目录下的python代码,代码第8行并不会报任何错误,但运行到第9行在map里却抛出找不到one模块。
该问题在分布式系统很常见。spark在执行rdd运行时,需要将rdd的代码和上下文打包发往不同的计算容器,以达到分布式计算的目的。上文代码执行到第9行时,代码执行环境已经改变,不再是当前目录,当然会报找不到one模块。
解决这个问题的办法很简单,就是把one模块所在的代码文件也发往map计算的容器
1
| sc = SparkContext(conf=conf, pyFiles=["one.py"])
|
其他类似的问题:
- 用mapreduce或者spark计算,如果需要读取本地文件,需要将文件同时发往集群中所有的机器,如果引用某个python包,需要在集群中所有机器都装上该依赖
- storm在写spout和bolt时,需要将不可序列化的字段加上transient关键字,否则会包序列化失败。原因是storm在分发任务需要将当前的上下文序列化包装成子任务发往worker。通常的做法是把所有的字段加上transient关键字,但这样写会导致构造函数的赋值都无效,而子任务发往worker后反序列化不会调用构造函数。因此storm的spout和bolt不建议写构造函数,而去覆盖prepare方法,需要传递给spout和bolt的参数通过storm的conf来传递。