我在Python中有这个有点复杂的命令行函数(让我们称之为myFunction()
),我正在努力将它集成到图形界面中(使用PySide / Qt)。
GUI用于帮助选择输入和显示输出。但是,myFunction
旨在作为独立的命令行函数工作,并且它偶尔会打印出进度。
我的问题是:如何拦截这些print
调用并在GUI中显示它们?
我知道可以修改myFunction()
以将processEvents()
发送到GUI,但我将失去在终端中执行myFunction()
的能力。
理想情况下,我想要类似于Ubuntu的图形软件更新程序,它有一个小的嵌入式终端外观小部件,显示它在终端中执行时显示的apt-get
。
答案 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__