截取python的“print”语句并在GUI中显示
我在Python中有一个有点复杂的命令行函数,我们称它为myFunction,我正在使用PySide/Qt将它集成到图形界面中 GUI用于帮助选择输入和显示输出。然而,myFunction被设计成一个独立的命令行函数,它偶尔会打印出进度 我的问题是:如何拦截这些打印调用并在GUI中显示它们? 我知道可以修改myFunction以将processEvents发送到GUI,但这样我就失去了在终端中执行myFunction的能力 理想情况下,我想要类似于Ubuntu图形软件更新程序的东西,它有一个小型嵌入式终端外观小部件,显示在终端中执行时apt get将显示的内容。所有打印都是通过sys.stdout完成的,sys.stdout是一个普通的类似文件的对象:iirc,它需要一个writest方法。只要你的替代者有这种方法,你就很容易陷入困境:截取python的“print”语句并在GUI中显示,python,Python,我在Python中有一个有点复杂的命令行函数,我们称它为myFunction,我正在使用PySide/Qt将它集成到图形界面中 GUI用于帮助选择输入和显示输出。然而,myFunction被设计成一个独立的命令行函数,它偶尔会打印出进度 我的问题是:如何拦截这些打印调用并在GUI中显示它们? 我知道可以修改myFunction以将processEvents发送到GUI,但这样我就失去了在终端中执行myFunction的能力 理想情况下,我想要类似于Ubuntu图形软件更新程序的东西,它有一个小型
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__