如何在调试模式下调用PySpark?

时间:2015-07-06 11:48:20

标签: python python-2.7 hadoop intellij-idea apache-spark

我使用Apache Spark 1.4设置了IntelliJ IDEA。

我希望能够将调试点添加到我的Spark Python脚本中,以便我可以轻松地调试它们。

我目前正在运行这一点来初始化spark过程

proc = subprocess.Popen([SPARK_SUBMIT_PATH, scriptFile, inputFile], shell=SHELL_OUTPUT, stdout=subprocess.PIPE)

if VERBOSE:
    print proc.stdout.read()
    print proc.stderr.read()

spark-submit最终调用myFirstSparkScript.py时,调试模式未启用,并且正常执行。遗憾的是,编辑Apache Spark源代码并运行自定义副本是不可接受的解决方案。

有谁知道是否可以在调试模式下使用spark-submit调用Apache Spark脚本?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:24)

据我了解你的意图,你想要的东西在Spark架构下是不可能直接实现的。即使没有subprocess调用,您可以直接在驱动程序上访问程序的唯一部分是SparkContext。从其他部分开始,您可以通过不同的通信层有效隔离,包括至少一个(在本地模式下)JVM实例。为了说明这一点,我们可以使用PySpark Internals documentation中的图表。

enter image description here

左侧框中的内容是可在本地访问的部分,可用于附加调试器。由于它最受限于JVM调用,因此除非您实际修改PySpark本身,否则实际上没有任何内容可供您使用。

右边的内容是远程发生的,从用户的角度来看,你使用的集群管理器几乎就是一个黑盒子。此外,在很多情况下,右边的Python代码只是调用JVM API。

这是不好的部分。好的部分是大多数时候不需要远程调试。除了可以轻松模拟的TaskContext访问对象之外,代码的每个部分都应该可以在本地轻松运行/测试,而无需使用Spark实例。

传递给操作/转换的函数采用标准和可预测的Python对象,并且还希望返回标准Python对象。同样重要的是这些应该是无副作用

因此,在一天结束时,你需要部分程序 - 一个薄层,可以交互式访问,并完全基于输入/输出和"计算核心"哪个不需要Spark进行测试/调试。

其他选项

据说你在这里并没有完全没有选择。

本地模式

被动地将调试器附加到正在运行的解释器

普通GDB和PySpark调试器都可以附加到正在运行的进程。一旦启动了PySpark守护程序和/或工作进程,就可以执行此操作。在本地模式下,您可以通过执行虚拟操作来强制它,例如:

sc.parallelize([], n).count()

其中n是多个"核心"在本地模式下可用(local[n])。在类Unix系统上逐步执行示例程序:

  • 启动PySpark shell:

    $SPARK_HOME/bin/pyspark 
    
  • 使用pgrep检查没有运行守护进程:

    ➜  spark-2.1.0-bin-hadoop2.7$ pgrep -f pyspark.daemon
    ➜  spark-2.1.0-bin-hadoop2.7$
    
  • 同样的事情可以通过以下方式在PyCharm中确定:

    alt + shift + a 并选择附加到本地流程

    enter image description here

    运行 - > 附加到本地流程

    此时你应该只看到PySpark shell(可能还有一些不相关的进程)。

    enter image description here

  • 执行虚拟动作:

    sc.parallelize([],1).count()

  • 现在您应该看到daemonworker(此处只有一个):

    ➜  spark-2.1.0-bin-hadoop2.7$ pgrep -f pyspark.daemon
    13990
    14046
    ➜  spark-2.1.0-bin-hadoop2.7$
    

    enter image description here

    较低pid的进程是守护进程,pid较高的进程是(可能)临时工作者。

  • 此时,您可以将调试程序附加到感兴趣的进程:

    • 在PyCharm中选择要连接的过程。
    • 通过调用简单的GDB:

      gdb python <pid of running process>
      

这种方法的最大缺点是你在适当的时候找到了正确的翻译。

分布式模式

使用连接到调试器服务器的活动组件

与PyCharm

PyCharm提供Python Debug Server,可以与PySpark作业一起使用。

首先,您应该为远程调试器添加配置:

  • alt + shift + a 并选择编辑配置运行 - &GT; 编辑配置
  • 点击添加新配置(绿色加号),然后选择 Python远程调试
  • 根据您自己的配置配置主机和端口(确保从远程计算机到达该端口)

    enter image description here

  • 启动调试服务器:

    + F9

    你应该看到调试器控制台:

    enter image description here

  • 确保工作节点上可以访问pyddev,方法是安装它或分发egg文件。

  • pydevd使用必须包含在您的代码中的活动组件:

    import pydevd
    pydevd.settrace(<host name>, port=<port number>)
    

    棘手的部分是找到包含它的正确位置,除非你调试批处理操作(比如传递给mapPartitions的函数),否则可能需要修补PySpark源本身,例如pyspark.daemon.worker或{{ 1}}像RDD这样的方法。让我们说我们对调试工作人员的行为很感兴趣。可能的补丁可能如下所示:

    RDD.mapPartitions

    如果您决定修补Spark源代码,请务必使用位于diff --git a/python/pyspark/daemon.py b/python/pyspark/daemon.py index 7f06d4288c..6cff353795 100644 --- a/python/pyspark/daemon.py +++ b/python/pyspark/daemon.py @@ -44,6 +44,9 @@ def worker(sock): """ Called by a worker process after the fork(). """ + import pydevd + pydevd.settrace('foobar', port=9999, stdoutToServer=True, stderrToServer=True) + signal.signal(SIGHUP, SIG_DFL) signal.signal(SIGCHLD, SIG_DFL) signal.signal(SIGTERM, SIG_DFL) 的已修补源代码未打包版本。

  • 执行PySpark代码。回到调试器控制台,玩得开心:

    enter image description here

其他工具

有许多工具,包括python-manholepyrasite,可以通过一些努力与PySpark一起使用。

注意

当然你可以使用&#34; remote&#34;具有本地模式的(主动)方法,并且在某种程度上&#34;本地&#34;具有分布式模式的方法(您可以连接到工作节点并执行与本地模式相同的步骤)。

答案 1 :(得分:0)

查看这个名为 pyspark_xray 的工具,下面是从其文档中提取的高级摘要。

pyspark_xray 是一个诊断工具,采用 Python 库的形式,供 pyspark 开发者在本地调试和排查 PySpark 应用程序,具体来说,它可以本地调试运行在从节点上的 PySpark RDD 或 DataFrame 转换函数。< /p>

开发 pyspark_xray 的目的是创建一个开发框架,使 PySpark 应用程序开发人员能够在本地进行调试和故障排除,并使用与 pyspark 应用程序相同的代码库远程进行生产运行。对于本地调试 Spark 应用代码部分,pyspark_xray 专门提供了本地调试运行在从节点上的 Spark 应用代码的能力,这个能力的缺失是目前 Spark 应用开发者的一个空缺。< /p>

问题

对于开发者来说,在本地对应用程序的每个部分进行分步调试非常重要,以便在开发过程中诊断、排除故障和解决问题。

如果您开发 PySpark 应用程序,您就会知道 PySpark 应用程序代码由两类组成:

  • 在主节点上运行的代码
  • 在工作节点/从节点上运行的代码

虽然主节点上的代码可以由本地调试器访问,但从节点上的代码就像一个黑匣子,调试器无法在本地访问。

网络上很多教程已经介绍了调试运行在主节点上的PySpark代码的步骤,但是当谈到调试运行在从节点上的PySpark代码时,没有找到解决方案,大多数人将这部分代码称为黑盒或不需要调试。

在从节点上运行的 Spark 代码包括但不限于:作为输入参数传递给 RDD transformation functions 的 lambda 函数。

解决方案

pyspark_xray 库使开发人员能够locally debug(步入)100% 的 Spark 应用程序代码,不仅是在主节点上运行的代码,还包括在从节点上运行的代码,使用 PyCharm 和其他VSCode等流行的IDE。

该库通过使用以下技术实现这些功能:

  • Spark 代码在从节点上的封装函数,查看the section了解更多详情
  • 在本地调试模式下对输入数据进行采样的实践,以便将应用程序放入独立本地 PC/Mac 的内存中
    • 例如,假设您的生产输入数据大小有 100 万行,显然无法放入一台独立 PC/Mac 的内存中,为了使用 pyspark_xray,您可以将 100 个样本行作为输入数据作为输入来调试您的应用程序本地使用 pyspark_xray
  • 使用标志自动检测本地模式CONST_BOOL_LOCAL_MODE 来自 pyspark_xray 的 const.py 自动检测本地模式是根据当前操作系统开启还是关闭,并带有值:
    • 真:如果当前操作系统是 Mac 或 Windows
    • 错误:否则

在您的 Spark 代码库中,您可以使用相同的代码库在本地调试和远程执行您的 Spark 应用程序。