PyQt5 Program Crashes While Updating QTextEdit via logging
I have a large program that takes a long time that needs ample logging. I have a GUI that is on the front end that includes a custom logging handler as defined below:
class QHandler(logging.Handler, QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = Lock()
def emit(self, record):
with self.emit_lock:
self.append(self.format(record))
self.autoScroll()
def format(self, record):
if (record.levelno <= logging.INFO):
bgcolor = WHITE
fgcolor = BLACK
if (record.levelno <= logging.WARNING):
bgcolor = YELLOW
fgcolor = BLACK
if (record.levelno <= logging.ERROR):
bgcolor = ORANGE
fgcolor = BLACK
if (record.levelno <= logging.CRITICAL):
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
I have the main gui (QMainWindow) that adds this handler via:
# inside __init__ of main GUI (QMainWindow):
self.status_handler = QHandler()
# Main gui is divided into tabs and the status handler box is added to the second tab
main_tabs.addTab(self.status_handler, 'Status')
And I have the controller function that initializes the logging handler via:
# inside controller initializing function
gui = gui_class() # this is the main gui that initializes the handler among other things
logger = logging.getLogger()
gui.status_handler.setFormatter(file_formatter) # defined elsewhere
logger.addHandler(gui.status_handler)
Once the GUI is raised and logging is initialized, I finish the python execution with:
app = QApplication.instance()
if (app is None):
app = QApplication()
app.setStyle('Fusion')
app.exec_()
The GUI has a few slots connected to pushbutton signals that spawns threads to do the actual processing. Each processing thread has it's own logging call which seems to work as intended. They are defined like follows:
class Subprocess_Thread(Thread):
def __init__(self, <args>):
Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
# does a bunch of stuff
self.logger.info('Running stuff')
# iterates over other objects and calls on them to do stuff
# where they also have a logger attached and called just like above
When I run my application without a GUI or even with the GUI minimized, it runs fine every time. I can see my log messages in the console (either command prompt or spyder
).
If I run the same application without minimizing the GUI, I will see the log messages in the GUI for initialization and some of the first parts of the threaded process, but then it will hang at seemingly random times. There is no error message and the CPU usage seems to be maxed out for the single core that is being used. I included a lock just to make sure logging
wasn't coming in from different threads, but that also didn't help.
I've tried going to a QPlainTextEdit
and a QListWidget
but I get the same problem every time.
Does anyone have an idea of why this GUI element would cause the entire Python interpreter to hang when in view and messages are logged to it?
python python-3.x logging pyqt5
add a comment |
I have a large program that takes a long time that needs ample logging. I have a GUI that is on the front end that includes a custom logging handler as defined below:
class QHandler(logging.Handler, QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = Lock()
def emit(self, record):
with self.emit_lock:
self.append(self.format(record))
self.autoScroll()
def format(self, record):
if (record.levelno <= logging.INFO):
bgcolor = WHITE
fgcolor = BLACK
if (record.levelno <= logging.WARNING):
bgcolor = YELLOW
fgcolor = BLACK
if (record.levelno <= logging.ERROR):
bgcolor = ORANGE
fgcolor = BLACK
if (record.levelno <= logging.CRITICAL):
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
I have the main gui (QMainWindow) that adds this handler via:
# inside __init__ of main GUI (QMainWindow):
self.status_handler = QHandler()
# Main gui is divided into tabs and the status handler box is added to the second tab
main_tabs.addTab(self.status_handler, 'Status')
And I have the controller function that initializes the logging handler via:
# inside controller initializing function
gui = gui_class() # this is the main gui that initializes the handler among other things
logger = logging.getLogger()
gui.status_handler.setFormatter(file_formatter) # defined elsewhere
logger.addHandler(gui.status_handler)
Once the GUI is raised and logging is initialized, I finish the python execution with:
app = QApplication.instance()
if (app is None):
app = QApplication()
app.setStyle('Fusion')
app.exec_()
The GUI has a few slots connected to pushbutton signals that spawns threads to do the actual processing. Each processing thread has it's own logging call which seems to work as intended. They are defined like follows:
class Subprocess_Thread(Thread):
def __init__(self, <args>):
Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
# does a bunch of stuff
self.logger.info('Running stuff')
# iterates over other objects and calls on them to do stuff
# where they also have a logger attached and called just like above
When I run my application without a GUI or even with the GUI minimized, it runs fine every time. I can see my log messages in the console (either command prompt or spyder
).
If I run the same application without minimizing the GUI, I will see the log messages in the GUI for initialization and some of the first parts of the threaded process, but then it will hang at seemingly random times. There is no error message and the CPU usage seems to be maxed out for the single core that is being used. I included a lock just to make sure logging
wasn't coming in from different threads, but that also didn't help.
I've tried going to a QPlainTextEdit
and a QListWidget
but I get the same problem every time.
Does anyone have an idea of why this GUI element would cause the entire Python interpreter to hang when in view and messages are logged to it?
python python-3.x logging pyqt5
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add theQHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.
– Joseph Martin
Nov 13 '18 at 17:37
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute namedlogger
that is justgetLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.
– Joseph Martin
Nov 13 '18 at 17:56
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01
add a comment |
I have a large program that takes a long time that needs ample logging. I have a GUI that is on the front end that includes a custom logging handler as defined below:
class QHandler(logging.Handler, QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = Lock()
def emit(self, record):
with self.emit_lock:
self.append(self.format(record))
self.autoScroll()
def format(self, record):
if (record.levelno <= logging.INFO):
bgcolor = WHITE
fgcolor = BLACK
if (record.levelno <= logging.WARNING):
bgcolor = YELLOW
fgcolor = BLACK
if (record.levelno <= logging.ERROR):
bgcolor = ORANGE
fgcolor = BLACK
if (record.levelno <= logging.CRITICAL):
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
I have the main gui (QMainWindow) that adds this handler via:
# inside __init__ of main GUI (QMainWindow):
self.status_handler = QHandler()
# Main gui is divided into tabs and the status handler box is added to the second tab
main_tabs.addTab(self.status_handler, 'Status')
And I have the controller function that initializes the logging handler via:
# inside controller initializing function
gui = gui_class() # this is the main gui that initializes the handler among other things
logger = logging.getLogger()
gui.status_handler.setFormatter(file_formatter) # defined elsewhere
logger.addHandler(gui.status_handler)
Once the GUI is raised and logging is initialized, I finish the python execution with:
app = QApplication.instance()
if (app is None):
app = QApplication()
app.setStyle('Fusion')
app.exec_()
The GUI has a few slots connected to pushbutton signals that spawns threads to do the actual processing. Each processing thread has it's own logging call which seems to work as intended. They are defined like follows:
class Subprocess_Thread(Thread):
def __init__(self, <args>):
Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
# does a bunch of stuff
self.logger.info('Running stuff')
# iterates over other objects and calls on them to do stuff
# where they also have a logger attached and called just like above
When I run my application without a GUI or even with the GUI minimized, it runs fine every time. I can see my log messages in the console (either command prompt or spyder
).
If I run the same application without minimizing the GUI, I will see the log messages in the GUI for initialization and some of the first parts of the threaded process, but then it will hang at seemingly random times. There is no error message and the CPU usage seems to be maxed out for the single core that is being used. I included a lock just to make sure logging
wasn't coming in from different threads, but that also didn't help.
I've tried going to a QPlainTextEdit
and a QListWidget
but I get the same problem every time.
Does anyone have an idea of why this GUI element would cause the entire Python interpreter to hang when in view and messages are logged to it?
python python-3.x logging pyqt5
I have a large program that takes a long time that needs ample logging. I have a GUI that is on the front end that includes a custom logging handler as defined below:
class QHandler(logging.Handler, QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = Lock()
def emit(self, record):
with self.emit_lock:
self.append(self.format(record))
self.autoScroll()
def format(self, record):
if (record.levelno <= logging.INFO):
bgcolor = WHITE
fgcolor = BLACK
if (record.levelno <= logging.WARNING):
bgcolor = YELLOW
fgcolor = BLACK
if (record.levelno <= logging.ERROR):
bgcolor = ORANGE
fgcolor = BLACK
if (record.levelno <= logging.CRITICAL):
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
I have the main gui (QMainWindow) that adds this handler via:
# inside __init__ of main GUI (QMainWindow):
self.status_handler = QHandler()
# Main gui is divided into tabs and the status handler box is added to the second tab
main_tabs.addTab(self.status_handler, 'Status')
And I have the controller function that initializes the logging handler via:
# inside controller initializing function
gui = gui_class() # this is the main gui that initializes the handler among other things
logger = logging.getLogger()
gui.status_handler.setFormatter(file_formatter) # defined elsewhere
logger.addHandler(gui.status_handler)
Once the GUI is raised and logging is initialized, I finish the python execution with:
app = QApplication.instance()
if (app is None):
app = QApplication()
app.setStyle('Fusion')
app.exec_()
The GUI has a few slots connected to pushbutton signals that spawns threads to do the actual processing. Each processing thread has it's own logging call which seems to work as intended. They are defined like follows:
class Subprocess_Thread(Thread):
def __init__(self, <args>):
Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
# does a bunch of stuff
self.logger.info('Running stuff')
# iterates over other objects and calls on them to do stuff
# where they also have a logger attached and called just like above
When I run my application without a GUI or even with the GUI minimized, it runs fine every time. I can see my log messages in the console (either command prompt or spyder
).
If I run the same application without minimizing the GUI, I will see the log messages in the GUI for initialization and some of the first parts of the threaded process, but then it will hang at seemingly random times. There is no error message and the CPU usage seems to be maxed out for the single core that is being used. I included a lock just to make sure logging
wasn't coming in from different threads, but that also didn't help.
I've tried going to a QPlainTextEdit
and a QListWidget
but I get the same problem every time.
Does anyone have an idea of why this GUI element would cause the entire Python interpreter to hang when in view and messages are logged to it?
python python-3.x logging pyqt5
python python-3.x logging pyqt5
edited Nov 13 '18 at 17:53
Joseph Martin
asked Nov 13 '18 at 16:16
Joseph MartinJoseph Martin
133
133
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add theQHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.
– Joseph Martin
Nov 13 '18 at 17:37
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute namedlogger
that is justgetLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.
– Joseph Martin
Nov 13 '18 at 17:56
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01
add a comment |
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add theQHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.
– Joseph Martin
Nov 13 '18 at 17:37
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute namedlogger
that is justgetLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.
– Joseph Martin
Nov 13 '18 at 17:56
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add the
QHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.– Joseph Martin
Nov 13 '18 at 17:37
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add the
QHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.– Joseph Martin
Nov 13 '18 at 17:37
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute named
logger
that is just getLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.– Joseph Martin
Nov 13 '18 at 17:56
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute named
logger
that is just getLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.– Joseph Martin
Nov 13 '18 at 17:56
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01
add a comment |
1 Answer
1
active
oldest
votes
The QHandler
that samples is not thread-safe so it will generate problems if you call it from another thread since it is a GUI, a possible solution is to send the data from the secondary thread(def emit(self, record):
) to the thread of the GUI through QMetaObject
for this you must use pyqtSlot
:
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
Example:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread '.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: , thread: ".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
This answer put me on the right path. I created my ownpyqtSignal
that is emitted when the emit function is called. Then I created adisplay
method that is a custompyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.
– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53285181%2fpyqt5-program-crashes-while-updating-qtextedit-via-logging%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The QHandler
that samples is not thread-safe so it will generate problems if you call it from another thread since it is a GUI, a possible solution is to send the data from the secondary thread(def emit(self, record):
) to the thread of the GUI through QMetaObject
for this you must use pyqtSlot
:
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
Example:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread '.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: , thread: ".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
This answer put me on the right path. I created my ownpyqtSignal
that is emitted when the emit function is called. Then I created adisplay
method that is a custompyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.
– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
add a comment |
The QHandler
that samples is not thread-safe so it will generate problems if you call it from another thread since it is a GUI, a possible solution is to send the data from the secondary thread(def emit(self, record):
) to the thread of the GUI through QMetaObject
for this you must use pyqtSlot
:
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
Example:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread '.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: , thread: ".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
This answer put me on the right path. I created my ownpyqtSignal
that is emitted when the emit function is called. Then I created adisplay
method that is a custompyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.
– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
add a comment |
The QHandler
that samples is not thread-safe so it will generate problems if you call it from another thread since it is a GUI, a possible solution is to send the data from the secondary thread(def emit(self, record):
) to the thread of the GUI through QMetaObject
for this you must use pyqtSlot
:
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
Example:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread '.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: , thread: ".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
The QHandler
that samples is not thread-safe so it will generate problems if you call it from another thread since it is a GUI, a possible solution is to send the data from the secondary thread(def emit(self, record):
) to the thread of the GUI through QMetaObject
for this you must use pyqtSlot
:
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
Example:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread '.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: , thread: ".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
answered Nov 13 '18 at 18:38
eyllanesceyllanesc
75.6k103156
75.6k103156
This answer put me on the right path. I created my ownpyqtSignal
that is emitted when the emit function is called. Then I created adisplay
method that is a custompyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.
– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
add a comment |
This answer put me on the right path. I created my ownpyqtSignal
that is emitted when the emit function is called. Then I created adisplay
method that is a custompyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.
– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
This answer put me on the right path. I created my own
pyqtSignal
that is emitted when the emit function is called. Then I created a display
method that is a custom pyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.– Joseph Martin
Nov 14 '18 at 12:07
This answer put me on the right path. I created my own
pyqtSignal
that is emitted when the emit function is called. Then I created a display
method that is a custom pyqt5Slot
that handles the actual GUI update. This seems to make it thread safe.– Joseph Martin
Nov 14 '18 at 12:07
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
@JosephMartin that is the other option, but for me it is easier to use QMetaObject.InvokedMethod since no connection or new signals are needed. both are thread-safe :-)
– eyllanesc
Nov 14 '18 at 12:10
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53285181%2fpyqt5-program-crashes-while-updating-qtextedit-via-logging%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
please provide a Minimal, Complete, and Verifiable example
– eyllanesc
Nov 13 '18 at 16:55
I added some more code to show how the logger and GUI are initialized. All I basically do is add the handler to a tab in the GUI, raise the GUI, and then add the
QHandler
to the root logger's handlers with the same format as what I use to log to a file. From there the controller starts a thread to run the processing while the GUI is maintained in the main thread. Logging calls are made in the processing thread and should be received by the GUI. Both the file output and console outputs are working just fine, the GUI handler freezes the whole app when it isn't minimized.– Joseph Martin
Nov 13 '18 at 17:37
you say I added some more code, for me that more code does not make it Minimal, Complete, and Verifiable example, so I'll ask you to try a little harder and provide a Minimal, Complete, and Verifiable example, so we'll also try to help you, for My problem is that you are using the logging incorrectly in another thread.
– eyllanesc
Nov 13 '18 at 17:41
I've added a bit more, but it's hard to add so much because this program is quite large and I can't copy the text directly into this question box. I know for a fact that the logging calls are fine because like I said I can run this with no problem if I don't add the GUI handler to the root logger, or even if I just keep it minimized. The threads don't do anything special, each object I've created whether it is a thread or not creates an attribute named
logger
that is justgetLogger
called with the class name string. Let me know what seems to be missing from above and I'll try to add it.– Joseph Martin
Nov 13 '18 at 17:56
Although seeing your code I can suspect where the problem is, nobody has asked you to show the code of your project, I have asked you to create a Minimal, Complete, and Verifiable example, that is, a minimum code that verifies your problem and does not need anything else to run.
– eyllanesc
Nov 13 '18 at 18:01