如何捕获Python解释器的输出并在Text控件中显示?
我有一个用Python和PyQt写的程序,专门在Windows上运行。这个程序会进行很多操作,并且打印出很多信息。不过因为我想把它打包成一个独立的应用,不想让命令提示符窗口出现,所以我希望所有的信息都能在主应用程序里显示,比如在一个QTextEdit控件里。请问我该怎么做,才能让程序在运行时把解释器的输出同时显示在textEdit里,就像在真实的解释器里那样?
5 个回答
我建议你使用日志库。你可以在这里找到相关文档:http://docs.python.org/library/logging.html。你还可以为QTextEdit写一个自己的日志处理器。这里有一个很好的教程,可以帮助你入门:http://pantburk.info/?blog=77
很遗憾,这个例子在使用PySide时不太管用。它会出现以下错误:
sys.stdout = EmittingStream(textWritten=self.write2Console)
AttributeError: 'textWritten()' is not a Qt property or a signal
为了让它能在PySide上正常运行,我们需要做以下修改:
sys.stdout = EmittingStream()
self.connect(sys.stdout,QtCore.SIGNAL('textWritten(QString)'),self.write2Console)
我想你提到的“解释器的输出”是指在控制台或终端窗口中显示的内容,比如用 print()
打印出来的东西。
Python 所有的控制台输出都会写入程序的输出流 sys.stdout
(正常输出)和 sys.stderr
(错误输出,比如异常的追踪信息)。这些输出流就像文件一样。
你可以用自己的文件样的对象来替换这些输出流。你只需要提供一个 write(text)
函数就可以了。通过提供你自己的实现,你可以把所有的输出转发到你的小部件上:
class MyStream(object):
def write(self, text):
# Add text to a QTextEdit...
sys.stdout = MyStream()
sys.stderr = MyStream()
如果你需要重置这些输出流,它们仍然可以通过 sys.__stdout__
和 sys.__stderr__
来访问:
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
更新
这里有一些适用于 PyQt4 的示例代码。首先定义一个流,它会通过 Qt 信号报告写入的数据:
from PyQt4 import QtCore
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
然后,在你的图形界面中,将这个流的实例安装到 sys.stdout
,并将 textWritten
信号连接到一个槽,这个槽会把文本写入到 QTextEdit
中:
# Within your main window class...
def __init__(self, parent=None, **kwargs):
# ...
# Install the custom output stream
sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
def __del__(self):
# Restore sys.stdout
sys.stdout = sys.__stdout__
def normalOutputWritten(self, text):
"""Append text to the QTextEdit."""
# Maybe QTextEdit.append() works as well, but this is how I do it:
cursor = self.textEdit.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(text)
self.textEdit.setTextCursor(cursor)
self.textEdit.ensureCursorVisible()