You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何管理PySpark作业中print语句的输出及文件重定向?

关于PySpark中print输出的定向问题

首先得明确:PySpark里的print()语句输出和Spark的log4j日志根本不是一回事儿——print()的内容是直接输出到驱动程序的标准输出(stdout),而log4j控制的是Spark框架本身的日志(包括Executor日志、Spark核心组件的INFO/WARN等日志),这就是为什么你改了conf/log4j.properties之后,只能看到INFO级别的框架日志,看不到print内容。

接下来分两种部署模式给你说解决方案:

1. Client部署模式(你例子里的--deploy-mode client

这种模式下,驱动程序是在你提交任务的本地机器上运行的,所以print的内容默认会打到本地的终端stdout里。

  • 最直接的方式就是你提到的shell重定向
    >或者>>把整个spark-submit命令的stdout重定向到文件,还可以加上2>&1把错误输出也一起定向,方便排查问题:

    /usr/bin/spark-submit --master yarn --deploy-mode client --queue default /home/hadoop/app.py > /home/hadoop/output 2>&1
    
  • 也可以在代码里手动重定向stdout
    如果不想用shell命令的方式,也可以在PySpark代码开头修改sys.stdout的指向,比如:

    import sys
    # 用追加模式打开文件,后续所有print都会写入这里
    sys.stdout = open('/home/hadoop/output', 'a')
    
    print("这条print内容会直接写到指定文件里")
    

    不过这种方式要注意:如果代码里有多线程操作,可能会出现输出混乱的问题;而且一旦修改了stdout,所有依赖stdout的输出都会进这个文件,包括PySpark本身的一些驱动端输出。

2. Cluster部署模式(--deploy-mode cluster

如果是Cluster模式,驱动程序是运行在YARN集群的某个节点上的,这时候本地的shell重定向完全没用,因为stdout不在你的本地机器上。

  • 查看YARN应用日志
    用YARN的日志命令就能拿到驱动程序的stdout内容,包括print的输出,还可以把输出重定向到本地文件:

    # 先获取应用ID,再导出日志
    yarn logs -applicationId application_xxxxxx_xxxx > /home/hadoop/output
    
  • 改用Spark日志API替代print
    如果想让这些输出和log4j的日志整合到一起,建议把print()替换成Spark的日志工具,比如用Python的logging模块配合Spark的日志配置:

    import logging
    
    # 获取Spark的日志实例
    logger = logging.getLogger("pyspark")
    logger.setLevel(logging.INFO)
    
    logger.info("这条内容会被log4j捕获,写入你配置的日志文件")
    

    这样只要你的log4j.properties配置正确,这些日志就会和Spark的INFO级日志一起写到指定文件里,不用再单独处理print的输出。

总结

回到你的问题:是不是必须用shell重定向?

  • 在Client模式下,shell重定向是最简单、最稳妥的方式,当然也可以用代码重定向stdout;
  • 在Cluster模式下,shell重定向无效,得通过YARN日志查看或者改用日志API来整合到log4j中。

内容的提问来源于stack exchange,提问作者simplycoding

火山引擎 最新活动