Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在调试模式下调用PySpark?_Python_Python 2.7_Hadoop_Intellij Idea_Apache Spark - Fatal编程技术网

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

Python 如何在调试模式下调用PySpark?,python,python-2.7,hadoop,intellij-idea,apache-spark,Python,Python 2.7,Hadoop,Intellij Idea,Apache Spark,我已经用ApacheSpark1.4设置了IntelliJ IDEA 我希望能够将调试点添加到Spark Python脚本中,以便能够轻松地调试它们 我目前正在运行这段Python来初始化spark进程 proc = subprocess.Popen([SPARK_SUBMIT_PATH, scriptFile, inputFile], shell=SHELL_OUTPUT, stdout=subprocess.PIPE) if VERBOSE: print proc.stdout.r

我已经用ApacheSpark1.4设置了IntelliJ IDEA

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

我目前正在运行这段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
时,调试模式未启用,并正常执行。不幸的是,编辑apachespark源代码并运行自定义副本不是一个可接受的解决方案


有人知道是否可以让spark submit在调试模式下调用Apache spark脚本吗?如果是,怎么做?

据我所知,鉴于Spark体系结构,您想要的东西是不可能直接实现的。即使没有
子进程
调用,程序中唯一可以直接在驱动程序上访问的部分就是
SparkContext
。通过不同的通信层,包括至少一个(在本地模式下)JVM实例,可以有效地将您与其余部分隔离开来。为了说明这一点,让我们使用来自的图表

左框中的是可在本地访问并可用于附加调试器的部分。因为它只限于JVM调用,所以实际上没有什么值得您感兴趣的,除非您实际修改PySpark本身

从用户的角度来看,右边的操作是远程进行的,这取决于您使用的集群管理器。此外,在许多情况下,右侧的Python代码只不过是调用JVMAPI

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

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

因此,在一天结束时,您必须访问程序的各个部分-一个可以交互访问和测试的薄层,它完全基于输入/输出和“计算核心”,不需要Spark进行测试/调试

其他选择 也就是说,你并不是完全没有选择

本地模式 (被动地将调试器附加到正在运行的解释器)

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

sc.parallelize([], n).count()
其中
n
是本地模式下可用的多个“核心”(
local[n]
)。在类Unix系统上逐步执行的示例过程:

  • 启动PySpark外壳:

    $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并选择附加到本地进程:

    或者运行->附加到本地进程

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

  • 执行虚拟操作:

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

  • 现在您应该看到
    守护进程
    工作者
    (这里只有一个):

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

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

    • 在PyCharm中,选择要连接的进程
    • 通过调用以下命令使用普通GDB:

      gdb python <pid of running process>
      
      棘手的部分是找到包含它的正确位置,除非您调试批处理操作(如传递给
      mapPartitions
      )它可能需要修补PySpark源本身,例如
      PySpark.daemon.worker
      RDD
      方法,如
      RDD.mapPartitions
      。假设我们对调试工作人员行为感兴趣。可能的修补程序如下所示:

      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)
      
      如果您决定修补Spark源代码,请确保使用位于
      $Spark\u HOME/python/lib
      中的修补源代码非打包版本

    • 执行PySpark代码。返回调试器控制台并享受乐趣:

    其他工具 有许多工具,包括或可以通过一些努力来使用PySpark

    注意


    当然,您可以在本地模式下使用“远程”(活动)方法,在某种程度上,也可以在分布式模式下使用“本地”方法(您可以连接到工作节点,并按照与本地模式相同的步骤进行操作)。

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

    是一种诊断工具,以Python库的形式,pyspark开发人员可以在本地调试和排除pyspark应用程序的故障,特别是它可以在本地调试在从属节点上运行的pyspark RDD或数据帧转换函数

    开发pyspark_X射线的目的是创建一个开发框架,使pyspark应用程序开发人员能够使用pyspark应用程序的相同代码库进行本地调试和故障排除,并远程执行生产运行。对于本地调试Spark应用程序代码的部分,pyspark_xray专门提供了本地调试在从属节点上运行的Spark应用程序代码的功能,该功能的缺失是Spark应用程序开发人员目前尚未填补的空白

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

    如果你开发PySpark
    import pydevd
    pydevd.settrace(<host name>, port=<port number>)
    
    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)