python – 从次要线程将stdout和stderr重定向到PyQt4 QTextEdit

栏目: 编程工具 · 发布时间: 7年前

内容简介:堆栈溢出.再次,我在一个迫切需要的时候来找你,在疯狂的边缘岌岌可危.这个问题 – 从标题可以看出,这是我在这里回答的另外几个问题的合并.我有一个PyQt应用程序,我想重新路由stdout和stderr流到我的GUI中的QTextEdit,没有延迟.最初,我发现以下堆栈溢出答案:

堆栈溢出.再次,我在一个迫切需要的时候来找你,在疯狂的边缘岌岌可危.这个问题 – 从标题可以看出,这是我在这里回答的另外几个问题的合并.

我有一个PyQt应用程序,我想重新路由stdout和stderr流到我的GUI中的QTextEdit,没有延迟.

最初,我发现以下堆栈溢出答案: http://stackoverflow.com/a/17145093/629404

这是完美的,但有一个警告:如果stdout或stderr在CPU处理相对较长的方法时多次更新,则当主线程返回到应用程序循环时,所有更新都将同时显示.不幸的是,我有几种方法需要长达20秒才能完成(网络相关),因此应用程序将无响应,并且QTextEdit不会更新 – 直到它们完成.

为了解决这个问题,我把所有的GUI处理委托给主线程,我已经产生了第二个线程来处理更长的网络操作,使用pyqtSignals通知主线程什么时候完成并通过回来的结果.当我开始测试这样写的代码时,python解释器立即开始崩溃,没有任何警告.

这是非常脆弱的地方:Python正在崩溃,因为 – 使用上面包含的链接中的类 – 我已将sys.stdout / err流分配给QTextEdit小部件; PyQt小部件不能从应用程序线程之外的任何线程修改,并且由于stdout和stderr的更新来自我创建的辅助工作线程,所以它们违反了此规则.我已经注释掉了我重定向输出流的代码段,当然这个程序运行没有错误.

这让我回到正方形,让我感到困惑;假设我继续处理主线程中的GUI相关操作,并处理次要线程中的计算和更长的操作(我明白是在用户触发事件时保持应用程序阻止的最佳方法),我怎么能将Stdout和Stderr从两个线程重定向到QTextEdit小部件?上述链接中的类对主线程工作正常,但是当更新来自第二个线程时,会杀死python – 因为上述原因.

首先,1为了实现线程不安全,许多堆栈溢出的例子是!

解决方案是使用线程安全对象(如Python Queue.Queue)来调解信息的传输.我附下了一些示例代码,将stdout重定向到Python Queue.该队列由QThread读取,QThread通过Qt的信号/时隙机制将内容发送到主线程(发出信号是线程安全的).然后,主线程将文本写入文本编辑.

希望这是明确的,如果不是,请随时问问题!

编辑:请注意,提供的代码示例不会很好地清理QThreads,所以当您退出时会收到警告.我会把它留给你扩展到你的用例并清理线程

import sys
from Queue import Queue
from PyQt4.QtCore import *
from PyQt4.QtGui import *

# The new Stream Object which replaces the default stream associated with sys.stdout
# This object just puts data in a queue!
class WriteStream(object):
    def __init__(self,queue):
        self.queue = queue

    def write(self, text):
        self.queue.put(text)

# A QObject (to be run in a QThread) which sits waiting for data to come through a Queue.Queue().
# It blocks until data is available, and one it has got something from the queue, it sends
# it to the "MainThread" by emitting a Qt Signal 
class MyReceiver(QObject):
    mysignal = pyqtSignal(str)

    def __init__(self,queue,*args,**kwargs):
        QObject.__init__(self,*args,**kwargs)
        self.queue = queue

    @pyqtSlot()
    def run(self):
        while True:
            text = self.queue.get()
            self.mysignal.emit(text)

# An example QObject (to be run in a QThread) which outputs information with print
class LongRunningThing(QObject):
    @pyqtSlot()
    def run(self):
        for i in range(1000):
            print i

# An Example application QWidget containing the textedit to redirect stdout to
class MyApp(QWidget):
    def __init__(self,*args,**kwargs):
        QWidget.__init__(self,*args,**kwargs)

        self.layout = QVBoxLayout(self)
        self.textedit = QTextEdit()
        self.button = QPushButton('start long running thread')
        self.button.clicked.connect(self.start_thread)
        self.layout.addWidget(self.textedit)
        self.layout.addWidget(self.button)

    @pyqtSlot(str)
    def append_text(self,text):
        self.textedit.moveCursor(QTextCursor.End)
        self.textedit.insertPlainText( text )

    @pyqtSlot()
    def start_thread(self):
        self.thread = QThread()
        self.long_running_thing = LongRunningThing()
        self.long_running_thing.moveToThread(self.thread)
        self.thread.started.connect(self.long_running_thing.run)
        self.thread.start()

# Create Queue and redirect sys.stdout to this queue
queue = Queue()
sys.stdout = WriteStream(queue)

# Create QApplication and QWidget
qapp = QApplication(sys.argv)  
app = MyApp()
app.show()

# Create thread that will listen on the other end of the queue, and send the text to the textedit in our application
thread = QThread()
my_receiver = MyReceiver(queue)
my_receiver.mysignal.connect(app.append_text)
my_receiver.moveToThread(thread)
thread.started.connect(my_receiver.run)
thread.start()

qapp.exec_()

http://stackoverflow.com/questions/21071448/redirecting-stdout-and-stderr-to-a-pyqt4-qtextedit-from-a-secondary-thread


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Apache Modules Book

The Apache Modules Book

Nick Kew / Prentice Hall PTR / 2007-02-05 / USD 54.99

"Do you learn best by example and experimentation? This book is ideal. Have your favorite editor and compiler ready-you'll encounter example code you'll want to try right away. You've picked the right......一起来看看 《The Apache Modules Book》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具