由于网上关于Pyspark的资料太过于零散,官方文档也没有中文版,所以只能自己尝试来翻译,第一次翻译文档,肯定会有很多谬误,希望大家能多评论指正,共同学习spark!
核心内容:
SparkContext:
Spark功能主要接口
RDD:
弹性分布式数据集,是Spark的基础概念
streaming.StramingContext:
Spark Streaming功能的主要接入口
streaming.DStream:
离散流,是Spark Streaming中的基本概念
sql.SQLContext:
DataFrame和sql功能的主要接口
sql.DataFrame:
已分组数据指定列的分布式数据集合
SparkConf
一个Spark应用的配置,用于设置key-value形式的Spark变量
大多数时候,你创建SparkConf时候用 SparkConf()的形式从spark.*Java系统属性中加载,在这种情况下
任何你直接设置的参数都会优先于系统属性。
对于单元测试,你可以直接调用SparkConf来跳过设置来得到相同的配置而不需要关心系统属性。
所有的设置方法都支持链式连接,如下:
conf.setMaster(“local”).setAppName(“My app”).
注意:一旦一个SparkConf已经传递给Spark,它就被复制且不能再被用户更改
contains(key)
查看配置是否有key
get(key, defaultValue=None)
拿到一个已经配置好的key的值,否则返回一个默认值
getAll()
拿到所有配置好的属性值
set(key, value)
设置属性
setAll(pairs)
批量设置参数,外部以列表形式,内部是key-value形式
setAppName(value)
设置应用名字
setExecutorEnv(key=None,value=None,pairs=None)
设置环境变量传送给线程池
setIfMissing(key,value)
若不存在则设置配置属性
setMaster(value)
设置主节点URL去连接
setSparkHome(value)
设置Spark在工作节点上的安装路径
setDebugString()
返回并打印配置信息
测试部分接口如下:
SparkContext
SparkContext 可以连接一个Spark集群,能够创建RDD和传送变量到集群
包扩展 = ('.zip', '.egg', '.jar')
accumulator(value,accum_param=None)
创建一个给定初始变量的累加器,用一个给定的累加器参数帮助对象(AccumulatorParam helper object)来
定义如何添加数据类型值。默认累加器参数只适用于整形和浮点型,如果需要其他类型的可以自己定义
addFile(path, recursive=False)
添加一个文件供Spark任务的每个节点下载使用,path可以是本地文件路径也可以是HDFS中文件(或者是
其他Hadoop支持的文件系统),也可以是http,https,ftp 地址。
为了将文件添加到到Spark任务中,使用文件名来寻找它的下载位置:
L{SparkFiles.get(fileName)<pyspark.files.SparkFiles.get>}
如果参数recusive(递归)设置为True,可以使用文件夹,但目前只支持Hadoop类的文件系统
操作示例如下:
addPyFile(path)
添加要给.py或者.zip文件给所有在SparkContext中将要执行的任务执行,Path可以是本地路径,HDFS或者是其他Hadoop支持的文件系统,http,https,ftp链接。
applicationId
一个Spark应用的唯一认证,格式依赖于调度器实现。
>>> sc.applicationId
'local-...'
binaryFiles(path,minPartitions=None)
读取二进制文件,可以是所有节点的本地文件系统,HDFS...每个文件作为单独记录,并返回键值对,keys是文件路径,
value是每个文件的内容
注意:推荐是小文件,大文件也可以,但是可能会效率较差
binaryRecords(path, recordLength)
从二进制文件中读取数据,假设每个记录都是一串指定数字格式的数字,每个记录的数字不变,path是文件路径
而recordLength是分割记录的长度。
broadcast(value)
向集群群发要给只读变量,返回一个用于在分布式对象中读取的对象,这个变量只会给每个集群发一次
cancelAllJobs()
取消所有已添加的或者正在运行的任务
setJobGroup(groupId,descriptiom,interruptOnCancel=False)
给所有在一个线程中任务分配一个groupId,经常会有单个应用的一个执行单元由多个Spark任务组成,应用开发者能用
这个方法来给所有任务分组和添加描述信息,一旦设定好,Spark UI会将任务与组联系起来
>>> import threading
>>> from time import sleep
>>> result = "Not Set"
>>> lock = threading.Lock()
>>> def map_func(x):
... sleep(100)
... raise Exception("Task should have been cancelled")
>>> def start_job(x):
... global result
... try:
... sc.setJobGroup("job_to_cancel", "some description")
... result = sc.parallelize(range(x)).map(map_func).collect()
... except Exception as e:
... result = "Cancelled"
... lock.release()
>>> def stop_job():
... sleep(5)
... sc.cancelJobGroup("job_to_cancel")
>>> supress = lock.acquire()
>>> supress = threading.Thread(target=start_job, args=(10,)).start()
>>> supress = threading.Thread(target=stop_job).start()
>>> supress = lock.acquire()
>>> print(result)
Cancelled
cancelJobGroup(groupId)
取消组内所有任务执行
defaultMinPartitions
默认HadoopRDDS的最小分块数
defaultParallelism
parallelism默认的level(如:reduce 任务)
dump_profiles(path)
将概要统计信息转储到目录路径中
emptyRDD()
创建一个没有分区和元素的RDD
getConf()
拿到该SparkContext的SparkConf对象
hadoopFile(path, inputFormatClass, keyClass, valueClass, keyConverter=None,
valueConverter=None, conf=None, batchSize=0)
以HDFS(本地文件系统)中任意一对key/value读取一个旧的Hadoop输入格式,原理和sc.sequenceFile
相同。
一个Hadoop配置能被以Python字典的形式传输,这将转化为Java中的配置
Path:Hadoop文件目录
inputFormatClass:Hadoop输入格式的全描述类名(eg:“org.apache.hadoop.mapred.TextInputFormat”)
keyClass:key可写类的全描述类名(e.g. “org.apache.hadoop.io.Text”)
valueClass:value可写类的全描述类名(e.g. “org.apache.hadoop.io.LongWritable”)
hadoopRDD(inputFormatClass, keyClass, valueClass, keyConverter=None, valueConverter=None,
conf=None, batchSize=0)
同上类似
parallelize(c, numSlices=None)
分配本地python集合来生成一个RDD,如果输入型式是一个范围可以用xrange
>>> sc.parallelize([0, 2, 3, 4, 6], 5).glom().collect()
[[0], [2], [3], [4], [6]]
>>> sc.parallelize(xrange(0, 6, 2), 5).glom().collect()
[[], [0], [], [2], [4]]
pickleFile(name,minPartits=None)
加载之前用RDD.saveAsPickleFile方法保存的RDD
tmpFile = NamedTemporaryFile(delete=True)
>>> tmpFile.close()
>>> sc.parallelize(range(10)).saveAsPickleFile(tmpFile.name, 5)
>>> sorted(sc.pickleFile(tmpFile.name, 3).collect())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(start,end=None,step=1,numSlices=None)
看代码自然懂
>>> sc.range(5).collect()
[0, 1, 2, 3, 4]
>>> sc.range(2, 4).collect()
[2, 3]
>>> sc.range(1, 7, 2).collect()
[1, 3, 5]
runJob(rdd,partitionFunc,partitions=None,allowLocal=False)
在指定的分区里执行partionFunc函数,以元素数组的形式返回结果,如果没有指定,就会一直轮询执行。
如上代码,test是分了3个分区的RDD,分别是0,2,4,函数中参数制定了只执行第二分区,得到结果是4
文档代码如下;
myRDD = sc.parallelize(range(6), 3)
>>> sc.runJob(myRDD, lambda part: [x * x for x in part], [0, 2], True)
[0, 1, 16, 25]
sequenceFile
(path, keyClass=None, valueClass=None, keyConverter=None, valueConverter=None,
minSplits=None, batchSize=0)
...
setLocalProperty(key,value)
设置一个影响从该线程提交的作业的本地属性,例如Spark fair调度器池
setLogLevel(logLevel)
控制日志级别,级别包括:ALL, DEBUG, ERROR, FATAL, INFO, OFF, TRACE, WARN
sparkUser()
获取当前在运行SparkContext的系统用户名
startTime
返回SparkContext的启动时间
stop()
中断停止SparkContext
textFile(name, minPartitions=None, use_unicode=True)
从HDFS,本地文件系统(所有节点可用),返回一个字符串RDD,如果use_unicode是False,字符串将是 str类型(utf-8编码)。
>>> path = os.path.join(tempdir, "sample-text.txt")
>>> with open(path, "w") as testFile:
... _ = testFile.write("Hello world!")
>>> textFile = sc.textFile(path)
>>> textFile.collect()
['Hello world!']
union(rdds)
创建RDD列表的合并集,代码如下:
>>> path = os.path.join(tempdir, "union-text.txt")
>>> with open(path, "w") as testFile:
... _ = testFile.write("Hello")
>>> textFile = sc.textFile(path)
>>> textFile.collect()
['Hello']
>>> parallelized = sc.parallelize(["World!"])
>>> sorted(sc.union([textFile, parallelized]).collect())
['Hello', 'World!']
wholeTextFiles(dirPath)
每个文件都被读为单独一份记录,返回一个键值对,key是文件目录,value是文件内容
>>> dirPath = os.path.join(tempdir, "files")
>>> os.mkdir(dirPath)
>>> with open(os.path.join(dirPath, "1.txt"), "w") as file1:
... _ = file1.write("1")
>>> with open(os.path.join(dirPath, "2.txt"), "w") as file2:
... _ = file2.write("2")
>>> textFiles = sc.wholeTextFiles(dirPath)
>>> sorted(textFiles.collect())
[('.../1.txt', '1'), ('.../2.txt', '2')]
pyspark.RDD
aggreate(zeroValue, seqOp, combOp)
aggregate先对每个分区的元素做聚集,然后对所有分区的结果做聚集,聚集过程中,使用的是给定的聚集函数以及初始值”zero value”。这个函数能返回一个与原始RDD不同的类型U,因此,需要一个合并RDD类型T到结果类型U的函数,还需要一个合并类型U的函数。这两个函数都可以修改和返回他们的第一个参数,而不是重新新建一个U类型的参数以避免重新分配内存。
参数zeroValue:seqOp
运算符的每个分区的累积结果的初始值以及combOp
运算符的不同分区的组合结果的初始值 - 这通常将是初始元素(例如“Nil”表的列表 连接或“0”表示求和)
参数seqOp: 每个分区累积结果的聚集函数。
参数combOp: 一个关联运算符用于组合不同分区的结果
>>> seqOp = (lambda x, y: (x[0] + y, x[1] + 1))
>>> combOp = (lambda x, y: (x[0] + y[0], x[1] + y[1]))
>>> sc.parallelize([1, 2, 3, 4]).aggregate((0, 0), seqOp, combOp)
(10, 4)
>>> sc.parallelize([]).aggregate((0, 0), seqOp, combOp)
(0, 0)
x是(0,0),y是[1,2,3,4]
执行过程:
首先定义要给初始值(0,0)
x[0]+1, x[1]+1
1+2,1+1
3+3,2+1
6+4,3+1
不断地将第一个计算结果当作第二个的zeroValue(类似reduce的操作形式)
如果分区了就各自计算,然后再相加
checkpoint
()
标记这个RDD作为检查标记点, 保存在SparkContext.setCheckpointDir()同样的文件集合中,所有与其父RDD对象的引用关系都会被移除
这个函数必须先在这个RDD执行任何任务之前先被唤起,强烈建议存在内存中不然存在文件中会要求重新计算。
coalesce
(numPartitions, shuffle=False)
>>> sc.parallelize([1, 2, 3, 4, 5], 3).glom().collect() [[1], [2, 3], [4, 5]] >>> sc.parallelize([1, 2, 3, 4, 5], 3).coalesce(1).glom().collect() [[1, 2, 3, 4, 5]]
collect()
返回一个包含RDD所有元素的列表
collectAdMap()
返回一个key-value对。
>>> m = sc.parallelize([(1, 2), (3, 4)]).collectAsMap() >>> m[1] 2 >>> m[3] 4
上两个方法都是只能建立在目标数据量不大的情况下,因为数据都会被写入内存。