我正在编写一个使用Pyspark进行一些计算的Python 3.6程序。我正在编写它,以便它的行为就像是一个适当的Unix程序,接受STDIN的输入并将输出发射到STDOUT。
java不在船上,语言默认值是注销到足够高的日志严重性给出的stdout。Pyspark对此并不陌生。
在导入任何PY4J库之前,我需要手动弄乱文件描述符,还是有某种方法可以从python side中敲击Java侧的java侧,以便所有登录都可以登录到stderr?
?我期望工作的一个kludge,但基本上不是这样:
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。
我讨厌其中的每个部分,但它似乎在起作用:
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()