【发布时间】:2019-01-17 11:45:15
【问题描述】:
我正在使用命令 spark-submit 启动一个 pyspark 脚本,将标准输出重定向到文件也使用 tee 来生成日志。
命令如下:
spark-submit test.py | tee test.xxx
问题是只有用户定义函数UDF内的print只打印在终端上而不是文件tee test.xxx,而所有其他打印都将写入终端和文件。
为了模拟这种行为,我创建了这个最小的完整工作示例:
from pyspark import SparkContext
import pyspark.sql.functions as F #udf, col, count, sum, when, avg, mean, min
from pyspark.sql import SQLContext
from pyspark.sql.types import *
def cutURL(input):
cutURL.lineNumber += 1
if input==None or input=="" or not(isinstance(input, str)):
print("WARNING: not proper string URL: empty or null. Possible line: " + str(cutURL.lineNumber))
res = "Unknown"
if input==None: print("string is none")
elif not(isinstance(input, str)): print("input not a string")
elif input=="": print("empty string")
return res
res = input
try:
if (bool(re.search("/devices(.+?)&maxdist=[0-9]+", input))):
res = re.search("/devices(.+?)&maxdist=[0-9]+", input).group()
else:
res = re.sub(r'.*?(/devices/[^/]*_)[^/_]*(/read)', r'\1\2', input)
except:
print("WARning in cutURL:")
print(" not matching regular expression: is the string")
return res
sc = SparkContext.getOrCreate()
sc.setLogLevel("WARN")
sqlContext = SQLContext(sc)
cutURL.lineNumber = 0
print("This will be printed to both file and terminal")
df = sqlContext.createDataFrame([None, "example", "others"], "string").toDF("url")
cut_URL_udf = F.udf(cutURL, StringType())
df2 = df.select(cut_URL_udf("url").alias("cut_URL"))
df2.show()
在这种情况下,字符串WARNING: not proper string URL: empty or null. Possible line: 仅打印在终端上,而不打印到文件中。
如何使 pyspark UDF 中生成的输出也重定向到文件?
编辑
为了更好地解释我的问题,我添加了print("This will be printed to both file and terminal") 行。这将打印到终端并记录到文件,而 udf 中的 print 仅到终端。
【问题讨论】:
-
我认为问题在于 pyspark 可能更改了您的标准输出,因此当您“打印”时它不会直接进入标准输出,从而绕过 tee。您可能需要手动控制输出句柄或使用日志记录模块来避免重新发明轮子
-
但是为什么它只改变 udf 内的打印?
-
不幸的是,我对 pyspark 不熟悉,所以我无法肯定地回答这个问题,但它可能会打开自己的进程并根据自己的内部逻辑处理输出,这是一种相当普遍的行为跨度>
标签: python python-3.x pyspark user-defined-functions tee