目录
RDD的操作与观察【私信领取PySpark_operation.ipynb文件~】
Python语法复习【注意事项】
在Windows上编写的.py文件,可能在每行末尾有不可见的字符^M,直接放到Linux上执行可能会出错。
# 用命令将^M符号替换,生成新的一个文件
cat -v hello2.py | sed -e '1,$s/\^M$//g' > hello2_new.py
一般来说,以下划线开头的标识符具有特殊的意义。
以单下划线开头的,代表不能直接访问的类属性,需要通过类接口来访问;
以双下划线开头的,代表类的私有成员;
以双下划线开头和结尾的,代表Python中的特殊方法。
Python利用下划线定义变量的方式不是真正的私有;
使用from module import * 不能导入或使用私有属性、方法
使用 import module 能导入并使用私有属性和方法。
id() 获取内存地址
del a 删除变量a,并释放变量资源
可以认为元组是只读的列表。
字典中的键必须是不可变类型,但值可以是任何类型。
创建一个空集合必须用set(),不能用{},{}表示一个空字典。
身份运算符用于判断两个变量是不是引用自同一个对象(is / is not)
"{:0>6}".format('123') 右对齐,整个长度为6,不足6位左边补0
# 字符串模板
tpl = 'Name:%(name)s, Price:%(price).2f'
book = {'name':'Python', 'price':69}
print(tpl % book)
## Name:Python, Price:69.00
匿名函数Lambda
主体是一个表达式,只能进行简单的逻辑处理。
Lambda创建的表达式有自己的命名空间,不能访问自己参数列表之外或全局命名空间中的变量。
例如:
sum = lambda x,y:x+y a = sum(1,2) a的值就是3
Python模块和包
MouduleNotFoundError异常
# 找不到模块,最简单的解决办法
import sys
sys.path.append('C:\\mymoudule')
Python面向对象
允许多个类及继承基类
派生类可以覆盖基类中的任何方法
方法中可以调用基类中的同名方法
以两个下划线开头的,是私有的属性和方法
Python异常和JSON处理
try...catch...expect....语句
# 示例
import sys
defe raiseErr():
return 1/0
try:
'''需要执行的代码'''
raiseErr()
except:
'''有异常,捕获,并处理'''
# Unexpected error: <class 'ZeroDivisionError'>
print("Unexpected error:", sys.exc_info()[0])
raise # 抛出异常
else:
'''没有异常执行的语句'''
print("执行无异常")
finally:
'''这里不管有没有异常,都会执行'''
print('============finally============')
JSON:Web开发中常见的一种数据交换格式
JSON模块:
json.dumps 对数据进行编码
json.loads 对数据进行解码
# 示例
import json
map1 = {
'name':'jack',
'age':32,
'likes':['movie','car']
}
# 字典类型转换为JSON
json_str = json.dumps(map1)
# JSON转换为字典
map2 = json.loads(json_str)
Python日期处理
提供了time和calendar模块,可以用于格式日期和时间;
时间间隔以秒为单位,是浮点小数。
# 示例
ipomrt time
# 获取时间戳
ticks = time.time()
# 格式化输出
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
import calndar
# cal中保存着2021年10月的日历
cal = calendar.month(2021, 10)
用PySpark建立第一个Spark RDD
RDD:Resiliennt Distributed Datasets,弹性分布式数据集
RDD将计算的中间结果缓存于计算机内存中
RDD可以看做是一个抽象的数据集合,通过不同分区,将数据实际映射到不同的节点上
RDD只读不能修改,分布式存储,内存计算,具有弹性(计算过程中,内存不足,将一部分数据落到磁盘上处理)
在Spark中建立RDD的方式
- 练习/测试
调用parallelize()方法
第一个参数是一个给定的集合
第二个参数是partition数量(分区),是可选的,默认会根据集群设置情况给定
- range方法建立
第一个参数是开始值
第二个参数是结束值(不包括)
第三个参数是步长
- 使用textFile方法
依赖本地文件系统,一般用于在本地临时性地处理一些存储了大量数据的文件
- 使用HDFS构建
依赖Hadoop集群环境
配置WindowsSpark环境
解压安装包
配置环境变量
在Path中设置 %SPARK_HOME%\bin;
设置SPARK_HOME环境
PySpark Shell会自动创建sc对象和spark对象,可以在交互式环境中直接调用
# Python Shell构建RDD示例
# PySpark Shell中一行一行输入
# 构建RDD,接受一个集合,返回一个包含多行文本 内容的RDD
rdd = sc.parallelize(["hello world","hello spark"]);
# 接受一个函数,用于遍历处理RDD中每行文本内容
rdd2 = rdd.flatMap(lambda line:line.split(" "));
# 在单词集合RDD上执行map操作
rdd3 = rdd2.map(lambda word:(word,1));
# 把所有RDD元素按照key进行分组,使用给定的函数,对具有相同key的多个value进行reduce操作,返回reduce后的(keey,value)
rdd5 = rdd3.reduceByKey(lambda a, b : a+b);
rdd5.collect();
quit();
PyCharm中编写创建RDD
文件——设置——项目——项目结构——添加内容根,将spark目录下python目录下lib目录下的两个zip文件导入进来
cmd中安装findspark和pyspark
pip install findspark
pip install pyspark
# 需要手动创建SparkContext实例
import findspark
findspark.init()
from pyspark import SparkConf, SparkContext
# 创建SparkContext实例
# setAppName设置本次程序的你们那个城,setMaster设置Spark Master的方式为local[*]
conf = SparkConf().setAppName("WordCount").setMaster("local[*]")
# 创建SparkConf实例sc
sc = SparkContext(conf=conf)
rdd = sc.parallelize(["hello world","hello spark"])
# 接受一个函数,用于遍历处理RDD中每行文本内容
rdd2 = rdd.flatMap(lambda line: line.split(" "))
# 在单词集合RDD上执行map操作
rdd3 = rdd2.map(lambda word: (word, 1))
# 把所有RDD元素按照key进行分组,使用给定的函数,对具有相同key的多个value进行reduce操作,返回reduce后的(keey,value)
rdd5 = rdd3.reduceByKey(lambda a, b: a+b)
print(rdd5.collect())
# 防止多次创建SparkContexts
sc.stop()
RDD的操作与观察
【使用Jupyter notebook更便捷,因此后面操作在Jupyter中进行】
一般包括两个操作算子
变换:懒执行,等到有动作的时候才真正进行计算并显示结果。Map/flatMap/groupByKey/reducecByKey等
动作:立即执行,对RDD给出一个计算结果,并把结果返回到驱动器(或存储到外部存储系统)中。colletc/count/take/top/first等
# first操作
import findspark
findspark.init()
from pyspark.sql import SparkSession
# 构建Spark对象
# 采用local模式,只使用一个CPU进行处理
# 使用getOrCreate()共享SparkContext。如果尚不存在,则创建SparkContext;如果已存在,则创建SparkContext的实例。
# getOrCreate使用参考链接:https://www.codenong.com/47813646/
spark = SparkSession.builder \
.master("local[1]") \
.appName("RDD Demo") \
.getOrCreate();
sc = spark.sparkContext
rdd = sc.parallelize(["a", "a", "c"])
# first获取第一个元素
print("first():", rdd.first())
# max获取RDD最大元素
print("max(): ", rdd.max())
# sum求和,设置两个分区
rdd2 = sc.parallelize([1, 2, 3, 4, 5], 2)
print("sum(): ", rdd2.sum())
# count操作
# 获取元素个数
print("[1, 2, 3, 4, 5]求count():", rdd2.count())
# 元素为[["a", "b"], "c"],其中第一个是一个序列,输出结果应该为2
rdd2a = sc.parallelize([["a", "b"], "c"])
print("[['a', 'b'], 'c']求count():", rdd2a.count())
# take操作
# rdd.take(n),其中n表示获取的个数,可以用来获取RDD中指定的前n个元素
# sc.parallelize(range(2, 100))等价于sc.range(2, 100)
rdd3 = sc.parallelize(range(2, 100))
print("take(10): ", rdd3.take(10))
# top操作
# rdd.top(n),其中n表示获取的个数
# 获取排序后的前n个元素
rdd4 = sc.parallelize([5, 6, 7, 3, 2, 10])
print("[5, 6, 7, 3, 2, 10]执行top(4):", rdd4.top(4))
# 可以接受另一个参数key=str,会按照字符串进行排序
print(
"key=str:", sc.parallelize([4, 3, 20, 2, 10]).top(10, key=str)
)
# collect()操作
# 将RDD数据转化为数组,同时从集群中拉取数据到driver端,对于少量数据的观察特别有用
rdd5 = sc.parallelize([("a", 2), ("b", "c")])
print('[("a", 2), ("b", "c")]求collect()操作', rdd5.collect())
# collectAsMap操作
# 适用于键值RDD,并将其转换为Map映射保留键值结构
m = rdd5.collectAsMap()
print('collectAsMap操作:', m)
# countByKey
# 统计RDD[K, V]中每个K的数量
rdd6 = sc.parallelize([('a', 1), ('b', 2), ('a', 3)])
# 利用sorted()进行升序排序,里面从元组变成列表也适用
print("countByKey操作: ", rdd6.countByKey())
其余操作见jupyter文件。
【函数中的输出会在控制台显示】