从Jython控制stdout/stderr

7 投票
2 回答
2614 浏览
提问于 2025-04-16 12:06

我在用jython调用一个Java库里的函数,这个函数会往标准输出(stdout)打印信息。我想在jython脚本中屏蔽掉这些输出。我尝试用Python的方式,把sys.stdout替换成一个像文件的对象(StringIO),但是这样并没有捕捉到Java库的输出。我在想,sys.stdout可能对Java程序没有影响。请问在jython中有没有什么标准的方法可以程序化地重定向或屏蔽这些输出?如果没有,还有什么其他方法可以做到这一点呢?

2 个回答

1

我创建了一个上下文管理器,用来模仿(Python3中的)contextlib的redirect_stdout功能,(这里有代码)

'''Wouldn't it be nice if sys.stdout knew how to redirect the JVM's stdout? Shooting star.
        Author: Sean Summers <seansummers@gmail.com> 2015-09-28 v0.1
        Permalink: https://gist.githubusercontent.com/seansummers/bbfe021e83935b3db01d/raw/redirect_java_stdout.py
'''

from java import io, lang

from contextlib import contextmanager

@contextmanager
def redirect_stdout(new_target):
        ''' Context manager for temporarily redirecting sys.stdout to another file or file-like object
                see contextlib.redirect_stdout documentation for usage
        '''

        # file objects aren't java.io.File objects...
        if isinstance(new_target, file):
                new_target.close()
                new_target = io.PrintStream(new_target.name)
        old_target, target = lang.System.out, new_target
        try:
                lang.System.setOut(target)
                yield None
        finally:
                lang.System.setOut(old_target)
9

你可以使用 System.setOut,像这样:

>>> from java.lang import System 
>>> from java.io import PrintStream, OutputStream
>>> oldOut = System.out
>>> class NoOutputStream(OutputStream):         
...     def write(self, b, off, len): pass      
... 
>>> System.setOut(PrintStream(NoOutputStream()))
>>> System.out.println('foo')                   
>>> System.setOut(oldOut)
>>> System.out.println('foo')                   
foo

需要注意的是,这个方法不会影响Python的输出,因为当Jython启动时,它会抓取 System.out,所以你可以像预期的那样重新设置 sys.stdout

撰写回答