- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
堆栈溢出。再一次,我在急需的时候来找你,在精神错乱的边缘摇摇欲坠。这个问题——从标题中可以看出——是我在这里看到的其他几个问题的合并。
我有一个 PyQt 应用程序,我想将 stdout 和 stderr 流重新路由到我的 GUI 中的 QTextEdit没有延迟。
最初,我找到了以下堆栈溢出答案: https://stackoverflow.com/a/17145093/629404
这很有效,但有一个警告:如果在 CPU 处理相对较长的方法时多次更新 stdout 或 stderr,所有更新都会在主线程返回应用程序循环时同时显示 。不幸的是,我有一些方法最多需要 20 秒才能完成(与网络相关),因此应用程序变得无响应 - 并且 QTextEdit 不会更新 - 直到它们完成。
为了解决这个问题,我将所有的 GUI 处理委托(delegate)给主线程,并且我一直在产生第二个线程来处理更长的网络操作,使用 pyqtSignals 来通知主线程何时工作完成并传回结果。当我开始测试以这种方式编写的代码时,python 解释器立即开始崩溃,没有任何警告。
这是非常令人沮丧的地方:Python 崩溃了,因为 - 使用上面包含的链接中的类 - 我已将 sys.stdout/err 流分配给 QTextEdit 小部件; PyQt 小部件不能从应用程序线程以外的任何线程修改,并且由于对 stdout 和 stderr 的更新来 self 创建的辅助工作线程,因此它们违反了此规则。我已注释掉我重定向输出流的代码部分,果然,程序运行没有错误。
这让我回到了原点,让我陷入了困惑的境地;假设我继续在主线程中处理与 GUI 相关的操作,并在辅助线程中处理计算和更长的操作(我已经明白这是防止应用程序在用户触发事件时阻塞的最佳方法),我怎么能将两个线程的 Stdout 和 Stderr 重定向到 QTextEdit 小部件?上面链接中的类在主线程中工作得很好,但是当更新来自第二个线程时,由于上述原因,杀死了 python。
最佳答案
首先,+1 用于实现线程不安全的许多堆栈溢出示例!
解决方案是使用线程安全对象(如 Python Queue.Queue
)来调解信息的传输。我在下面附上了一些示例代码,它们将 stdout
重定向到 Python Queue
。 Queue
被 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_()
关于python - 将 stdout 和 stderr 从辅助线程重定向到 PyQt4 QTextEdit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21071448/
我想阅读 php://stderr。怎么做到的? php://stderr 和 STDERR 是否写入同一个文件?因为在写入 php://stderr 后,我尝试使用 stream_get_conte
我不确定这个问题是 Python 还是 shell 问题。 我有一个 Python 程序,它在命令上使用子进程调用,该命令可以在 stderr 上发出错误消息。我自己的程序也使用 sys.stderr
如何重定向命令的输出,以便 stdout 和 stderr 都记录在文件中,并且我仍然希望 stderr 显示为输出。 我也不想使用 bash 来执行此操作。有这样的办法吗? 最佳答案 这很简单: $
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
我得到了以下批处理命令 echo 1 & echo 2 1>&2 & echo 3 有时这会打印 1 2 3有时 132 我怎样才能控制顺序?我必须得到订单。 是否有启用以下功能的命令? echo 1
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Ruby $stdout vs. STDOUT STDERR 通常比使用 $stderr 更受青睐,还是相反
这是我经常尝试完成的任务。我想将 stderr 和 stdout 都记录到日志文件中。但我只想打印到控制台 stderr。 我尝试过使用 tee,但是一旦我使用“2>&1”合并了 stderr 和 s
我想要做的是将 stderr 重定向到 stdout,而不更改 stderr 的输出。 比如说,命令在stderr中有输出,我想将stderr中的所有内容输出到屏幕,同时还通过grep处理信息并将其保
我正在尝试重定向一些 bash 脚本输出。我想做的是: ./some_script.sh 2> error.log >> all_output.log 2>&1 我想将 stderr 放在一个文件中,
我想将 stdout 和 stderr 的输出重定向到一个公共(public)文件: ./foo.sh >stdout_and_stderr.txt 2>&1 但也只是将 stderr 重定向到一个单
我想运行几个命令,并将所有输出捕获到日志文件中。我还想将任何错误打印到屏幕上(或者可以选择将输出邮寄给某人)。 这是一个例子。以下命令将运行三个命令,并将所有输出(STDOUT 和 STDERR)写入
在其他语言中(如 bash 和 Python),当我们生成一个子进程时,这个新进程将从父进程继承 stdout 和 stderr。这意味着子进程的任何输出都将打印到终端以及父进程的输出。 我们如何在
这个问题在这里已经有了答案: IO Redirection - Swapping stdout and stderr (4 个答案) 关闭 7 年前。 我想将应该转到 stdout 的所有内容重定向
我有一个 shell 脚本,我想将其 stdout 和 stderr 写入日志文件。我知道这可以通过 sh script.sh >> both.log 2>&1 但是,我还想同时将 stderr 写入
git clone 将其输出写入 stderr,如记录 here .我可以使用以下命令重定向它: git clone https://myrepo c:\repo 2>&1 但这会将所有输出(包括错误
以下将 stdout 写入日志文件并打印 stderr: bash script.sh >> out.log 这再次将 stdout 和 stderr 写入日志文件: bash script.sh >
我正在调试一个在 PHP 5.4 上使用 Slim 和 NotORM 的项目。将 NotORM 设置为 Debug模式时,NotORM 跟踪语句: fwrite(STDERR, "$backtrace
到目前为止我所做的是: #!/bin/bash exec 2> >(sed 's/^/ERROR= /') var=$( sleep 1 ; hostname ;
我在远程机器上通过 SSH 执行一系列操作,我正在传输它的标准输出和标准错误,然后由写入器使用它,写入本地标准输出和标准错误,以及字节缓冲区。 就在编写器使用它之前,我想对其执行一系列字符串操作,然后
现在我有一些使用 Popen.communicate() 的代码从子进程(设置 stdin=PIPE 和 stderr=PIPE)运行命令并捕获 stderr 和 stdout。 问题在于 commu
我是一名优秀的程序员,十分优秀!