我如何防止Java库污染Stdout



我正在编写一个使用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()

最新更新