我上个月开始使用Pyspark。我正在使用JupyterLab,并且只在本地执行代码。我试图编写一个使用Spark和Python的项目,但我开始在Spark变量方面遇到一些问题。当我说Spark变量时,我指的是这些变量:
from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession
conf = SparkConf().setAppName('local').setMaster('local')
sc = SparkContext(conf=conf)
spark = SparkSession(sc)
这是我的项目中的目录示例
例如,我创建了SparkUtils.py文件,以便在笔记本电脑上启动Spark,而不需要之前注释的conf、sc和Spark的调用。这很好用。当我想在其他文件中使用spark变量时,问题就开始了,例如DataProviders.py中的代码片段:
sku = spark.read.format("csv")
.option("header", "true")
.option("inferSchema", "true")
.load(path_to_sku)
.drop("_c0")
spark是如何在笔记本中启动的,DataProviders函数范围中没有变量spark。如果我使用Scala,我会构建一些特性,并将DataProviders类扩展到这个特性,因此Spark上下文和特性将是隐式的。但我不知道如何使用Python做同样的事情,也不知道是否有其他方法可以做到这一点。我目前解决这个问题的方法是,当函数需要使用spark变量时,我只需在每个代码上添加这一行:
spark = SparkSession.getActiveSession()
但这远不是最好的解决方案,我重复代码,这也远不是最佳实践。。。有人知道另一种解决方法吗?
SparkSession
是一个单例,因此SparkSession.getActiveSession()
通常每次调用它都会返回相同的会话。我可以理解避免代码重复的愿望,但这是一个简短的1行,具有非常清晰的行为。我不确定这种方法是否还有其他问题,但每次想要访问SparkSession
时都可以调用getActiveSession()
。
最常见的替代方案是在一个python模块(也称为文件(中定义spark
,并在其他模块中从该模块导入spark
。
例如,如果utils.SparkUtils.py
定义了火花变量,则可以将以下内容添加到etl.building.DataProviders.py
中:
from utils.SparkUtils import conf, sc, spark
如果您来自Scala,我建议您将每个Python模块视为Scala单例object
的粗略等价物。它是一个命名空间,您可以在其中定义可以从其他模块导入和调用的变量和函数。