我正在编写一个使用pyspark进行计算的python 3.6程序。我正在编写它,以便它可以像正常的UNIX程序一样工作,接受来自STDIN的输入并将输出发送到STDOUT。
未安装Java,并且在给定足够高的日志严重性的情况下,默认的语言是注销到STDOUT。 pyspark对此并不陌生。
在导入任何py4j库之前,我是否需要手动弄乱我的文件描述符,还是有某种方法可以从Python端处理Java端的事情,以便所有日志记录都进入STDERR?
我曾希望工作但基本上没有参加的kludge是this:
import contextlib
import sys
@contextlib.contextmanager
def impolite_library_wrapper():
real_out = sys.stdout
sys.stdout = sys.stderr
yield
sys.stdout = real_out
with impolite_library_wrapper():
import pyspark.sql
spark_builder = pyspark.sql.SparkSession.builder.enableHiveSupport()
spark = spark_builder.getOrCreate()
print("pls")
...我可以在这样的最小环境中运行:
$ bash
$ mkdir /tmp/pls
$ cd /tmp/pls
$ pipenv install pyspark==2.3
$ env -i "PATH=$PATH" pipenv run python wtf.py 2>/dev/null
2019-05-20 17:10:54 WARN Utils:66 - Your hostname, <redacted> resolves to a loopback address...
2019-05-20 17:10:54 WARN Utils:66 - Set SPARK_LOCAL_IP if you need to bind to another address
2019-05-20 17:10:55 WARN NativeCodeLoader:62 - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
pls
我希望这会输出pls
,并且只输出pls
。
我看到pyspark将在Spark 3.0中使用SPARK-21094专门解决此问题;我可以接受针对pyspark的答案,但是我目前的目标是Spark 2.3。
答案 0 :(得分:1)
我讨厌其中的每一个部分,但似乎有效:
import contextlib
import sys
import subprocess
class StderrOnlyPopen(subprocess.Popen):
def __init__(self, args, bufsize=-1, executable=None,
stdin=None, stdout=sys.stderr, *more, **kwmore):
super().__init__(args, bufsize, executable,
stdin, stdout, *more, **kwmore)
@contextlib.contextmanager
def impolite_library_wrapper():
real_Popen = subprocess.Popen
subprocess.Popen = StderrOnlyPopen
yield
subprocess.Popen = real_Popen
with impolite_library_wrapper():
import pyspark.sql
spark_builder = pyspark.sql.SparkSession.builder.enableHiveSupport()
spark = spark_builder.getOrCreate()