Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
截取python的“print”语句并在GUI中显示_Python - Fatal编程技术网

截取python的“print”语句并在GUI中显示

截取python的“print”语句并在GUI中显示,python,Python,我在Python中有一个有点复杂的命令行函数,我们称它为myFunction,我正在使用PySide/Qt将它集成到图形界面中 GUI用于帮助选择输入和显示输出。然而,myFunction被设计成一个独立的命令行函数,它偶尔会打印出进度 我的问题是:如何拦截这些打印调用并在GUI中显示它们? 我知道可以修改myFunction以将processEvents发送到GUI,但这样我就失去了在终端中执行myFunction的能力 理想情况下,我想要类似于Ubuntu图形软件更新程序的东西,它有一个小型

我在Python中有一个有点复杂的命令行函数,我们称它为myFunction,我正在使用PySide/Qt将它集成到图形界面中

GUI用于帮助选择输入和显示输出。然而,myFunction被设计成一个独立的命令行函数,它偶尔会打印出进度

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

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

所有打印都是通过sys.stdout完成的,sys.stdout是一个普通的类似文件的对象:iirc,它需要一个writest方法。只要你的替代者有这种方法,你就很容易陷入困境:

import sys

class CaptureOutput:
    def write(self, message):
        log_message_to_textbox(message)

sys.stdout = CaptureOutput()

日志消息到文本框的实际内容由您决定。

您可以重定向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()

用劫持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
然后只需提供一个支持写入的类似文件的对象:

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

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时使用它:


下面是一个使用contextmanager的Python3模式,它既封装了sys.stdout,又确保在出现异常时恢复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__

从初步测试来看,这似乎是我想要的。我可以截取打印输出并将其存储在变量中。现在,我只需要找到一种方式来显示它,这样我的GUI就不会看起来冻结,但这是另一个问题!谢谢,非常有帮助。只是def stdin2filefunc,文件有一个微妙的错误:文件参数在尝试使用redirect_stdin作为修饰符时会导致错误,所以应该改为def stdin2filefunc。
@redirect_stdin(GUIWriter())
def MyFunction(a, b, c, d):
  # any calls to print will call the 'write' method of the GUIWriter
  # do stuff
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__