我已经在Spark-Submit命令周围创建了一个包装器,以便能够通过解析日志来生成实时事件。 目的是创建一个实时界面,以显示Spark作业的详细进度。
因此包装器将如下所示:
submitter = SparkSubmitter()
submitter.submit('/path/to/spark-code.py')
for log_event in submitter:
if log_event:
print('Event:', log_event)
输出将如下所示:
Event: StartSparkContextEvent()
Event: StartWorkEvent()
Event: FinishWorkEvent()
Event: StopSparkContextEvent()
在内部,SparkSubmitter类将spark-submit命令作为子进程启动.Popen进程,然后在stdout流上进行迭代,并通过解析由该进程生成的日志来返回事件,如下所示:
class SparkSubmitter():
def submit(self, path):
command = self.build_spark_submit_command(path)
self.process = Popen(command, stdout=PIPE, stderr=PIPE)
def __iter__(self):
return self
def __next__(self):
# note: this is a IO-Blocking command
log = self.process.stdout.readline().decode('utf-8')
return self.parse_log_and_return_event(log)
此实现与Spark Standalone集群一起很好地工作。但是在纱线群集上运行时出现问题。
在纱线簇中,“火花相关日志”出现在stderr
中,而不是stdout
中。因此,我的课程无法解析由火花生成的日志,因为它仅试图读取stdout
。
问题1 :是否可以将Popen的stdout和stderr作为单个流读取?
问题2 :由于stdout和stderr都是Streams,是否可以合并两个Streams并将它们作为一个读取?
问题3 :是否可以将所有日志重定向到仅标准输出?
答案 0 :(得分:2)
对所有3个问题的回答都是“是”,您可以使用stderr=subprocess.STDOUT
作为Popen
的参数来将输出从stderr
重定向到stdout
:
self.process = Popen(command, stdout=PIPE, stderr=subprocess.STDOUT)