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

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

内容简介:堆栈溢出.再次,我在一个迫切需要的时候来找你,在疯狂的边缘岌岌可危.这个问题 – 从标题可以看出,这是我在这里回答的另外几个问题的合并.我有一个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


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

查看所有标签

猜你喜欢:

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

点击的奥秘:运用说服心理术提升在线影响力(全彩)

点击的奥秘:运用说服心理术提升在线影响力(全彩)

Nathalie Nahai(娜塔莉.纳海) / 陈旭 / 电子工业出版社 / 2014-9-1 / 75.00元

用户的每一次点击,不管是在虚拟商店购物,还是在浏览企业网站,或是漫无目的地把玩手机,都蕴藏着基于心理学的无穷奥秘。《点击的奥秘:运用说服心理术提升在线影响力》作者为全球知名的网络心理学家,其在《点击的奥秘:运用说服心理术提升在线影响力》中将心理学、神经科学及行为经济学巧妙地结合在一起,挖掘和提炼出一套行之有效的网络用户引导策略——既涵盖在线说服最新研究动向,也包括最前沿的科技成果,以及其他诸多惊人......一起来看看 《点击的奥秘:运用说服心理术提升在线影响力(全彩)》 这本书的介绍吧!

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

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具