拦截python的`print`语句并在GUI中显示

时间:2013-06-12 14:02:27

标签: python

我在Python中有这个有点复杂的命令行函数(让我们称之为myFunction()),我正在努力将它集成到图形界面中(使用PySide / Qt)。

GUI用于帮助选择输入和显示输出。但是,myFunction旨在作为独立的命令行函数工作,并且它偶尔会打印出进度。

我的问题是:如何拦截这些print调用并在GUI中显示它们? 我知道可以修改myFunction()以将processEvents()发送到GUI,但我将失去在终端中执行myFunction()的能力。

理想情况下,我想要类似于Ubuntu的图形软件更新程序,它有一个小的嵌入式终端外观小部件,显示它在终端中执行时显示的apt-get

4 个答案:

答案 0 :(得分:5)

你可以重定向stdout并在之后恢复。例如:

import StringIO
import sys

# somewhere to store output
out = StringIO.StringIO()

# set stdout to our StringIO instance
sys.stdout = out

# print something (nothing will print)
print 'herp derp'

# restore stdout so we can really print (__stdout__ stores the original stdout)
sys.stdout = sys.__stdout__

# print the stored value from previous print
print out.getvalue()

答案 1 :(得分:1)

用劫持stdout的函数包裹它:

def stdin2file(func, file):
  def innerfunc(*args, **kwargs):
    old = sys.stdout
    sys.stdout = file
    try:
      return func(*args, **kwargs)
    finally:
      sys.stdout = old
  return innerfunc

然后只需提供一个支持write()的对象文件:

class GUIWriter:
  def write(self, stuff):
    #send stuff to GUI

MyFunction = stdin2file(MyFunction, GUIWriter())

包装器也可以变成装饰器:

def redirect_stdin(file):
  def stdin2file(func, file):
    def innerfunc(*args, **kwargs):
      old = sys.stdout
      sys.stdout = file
      try:
        return func(*args, **kwargs)
      finally:
        sys.stdout = old
    return innerfunc
  return stdin2file

在声明MyFunction()时使用它:

@redirect_stdin(GUIWriter())
def MyFunction(a, b, c, d):
  # any calls to print will call the 'write' method of the GUIWriter
  # do stuff

答案 2 :(得分:0)

所有打印都是通过sys.stdout完成的,write(str)是一个普通的文件对象:iirc,它需要一个方法import sys class CaptureOutput: def write(self, message): log_message_to_textbox(message) sys.stdout = CaptureOutput() 。只要您的替换方法具有该方法,就可以很容易地放下钩子:

log_message_to_textbox

{{1}}的实际内容取决于您。

答案 3 :(得分:0)

这是一个使用contextmanager的Python 3模式,它同时封装了the monkey-patch technique,并确保在发生异常时恢复sys.stdout

from io import StringIO
import sys
from contextlib import contextmanager


@contextmanager
def capture_stdout():
    """
    context manager encapsulating a pattern for capturing stdout writes
    and restoring sys.stdout even upon exceptions

    Examples:
    >>> with capture_stdout() as get_value:
    >>>     print("here is a print")
    >>>     captured = get_value()
    >>> print('Gotcha: ' + captured)

    >>> with capture_stdout() as get_value:
    >>>     print("here is a print")
    >>>     raise Exception('oh no!')
    >>> print('Does printing still work?')
    """
    # Redirect sys.stdout
    out = StringIO()
    sys.stdout = out
    # Yield a method clients can use to obtain the value
    try:
        yield out.getvalue
    finally:
        # Restore the normal stdout
        sys.stdout = sys.__stdout__