堆栈溢出。我再次在迫切需要的时候来到你身边,在 精神错乱 的边缘摇摇欲坠。从标题可以明显看出,这个问题是我在这里看到的其他几个问题的结合。
我有一个PyQt应用程序,我想将stdout和stderr流重新路由到GUI中的QTextEdit 而不延迟 。
最初,我发现以下堆栈溢出答案: http://codingdict.com/questions/160679
这完美地工作了,但有一个警告:如果在CPU处理相对较长的方法时多次更新stdout或stderr,则 当主线程返回到应用程序循环时 ,
所有更新同时显示 。不幸的是,我有几种方法可能需要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
。这Queue
是由a读取的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_()
问题内容: 我想将子进程的stderr输出重定向到stdout。常量应该这样做,不是吗? 然而, 确实 输出了一些东西。为什么会这样,如何在stdout上得到错误消息? 问题答案: 仔细阅读源代码即可得出答案。特别是,该文档在显示以下内容时会产生误导: 表示(…)的特殊值表示标准错误应与标准输出进入同一 句柄 。 由于在求值时stdout设置为“默认”(技术上来说),因此stderr也设置为“默认
问题内容: 我在cyberciti.biz的评论中看到了这个有趣的问题。 我发现我什至找不到在sh的单行命令中执行此操作的灵活方法。 到目前为止,我对解决方案的想法是: 但是您会看到,这不是同步的,而且致命的是,它是如此丑陋。 欢迎与您分享这个想法。:) 问题答案: 你要 这里的顺序很重要。假设stdin(fd 0),stdout(fd 1)和stderr(fd 2)最初都连接到tty,因此 首先
我想将stdout和stderr重定向到一个文件,同时保留输出顺序,然后还将stderr显示到屏幕上。我看到很多问题讨论它: https://unix.stackexchange.com/questions/9646/show-only-stderr-on-screen-but-write-both-stdout-and-stderr-to-file https://unix.stackexcha
我有一个调用函数的PowerShell脚本。我正在努力实现所有这些,但不确定如何实现: 将标准输出写入控制台并输出。txt 将STDERR写入控制台并输出。txt和err。txt 确保所有STDOUT和STDERR输出仍按其生成的顺序 这就是我到目前为止所拥有的将STDOUT和STDERR写入文件的功能,但它不能完成我需要的其余部分。
很好的一天。我有一系列的命令,我想通过一个函数来执行,这样我就可以得到退出代码并相应地执行控制台输出。话虽如此,我这里有两个问题: 1) 我似乎无法将stderr指向/dev/null。 2) 在执行$1之前,不会显示第一条回显行。直到我运行需要一段时间才能处理的命令,比如在硬盘上搜索文件,我才真正注意到这一点。此外,情况显然是这样,因为输出如下所示: 换句话说,stderr显示在“尝试…$2”之
在 Linux 中,一切都只是文件。这意味着,对于控制台程序: 键盘表示为一个文件,Bash 从中读取你的输入。 显示器表示为一个文件,Bash向输出写入它。 让我们假设,你有一个程序可以计算文件中的行。你可以通过键入wc -l来调用它。现在尝试一下 没有发生什么事吧?它只是卡在那里。错了,它正在等待你的输入。这是它的工作原理: line_counter = 0 while end of file
问题内容: 要将 stdout 重定向到Bash中的截断文件,我知道使用: 为了重定向Bash中的 stdout ,将其附加到文件中,我知道要使用: 要将 stdout 和 stderr 都重定向到截断的文件,我知道使用: 如何将 stdout 和 stderr 都重定向到文件?没有为我工作。 问题答案: Bash执行从左到右的重定向,如下所示: :以追加模式打开并在那里重定向。 :重定向到 “当
问题内容: 我想从Groovy程序中执行foo.bat,并将生成的进程的输出重定向到stdout。Java或Groovy代码示例都可以。 foo.bat可能需要花费几分钟才能运行并生成大量输出,因此我希望在生成后立即查看输出,而不是必须等到该过程完成之后才能立即查看所有输出。 问题答案: 它使用一个类读取执行的程序生成的所有输出,并将其显示在其自己的stdout中。