У меня есть большая программа, которая занимает много времени и требует достаточно регистрации. У меня есть графический интерфейс пользователя, который включает в себя пользовательский обработчик журналов, как определено ниже:
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())
У меня есть основной графический интерфейс (QMainWindow), который добавляет этот обработчик через:
# 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')
И у меня есть функция контроллера, которая инициализирует обработчик регистрации через:
# 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)
После того, как GUI поднят и инициализирована регистрация, я завершаю выполнение python:
app = QApplication.instance()
if (app is None):
app = QApplication([])
app.setStyle('Fusion')
app.exec_()
В GUI есть несколько слотов, подключенных к кнопочным сигналам, которые порождают потоки для выполнения фактической обработки. Каждый поток обработки имеет свой собственный вызов регистрации, который, кажется, работает как задумано. Они определены следующим образом:
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
Когда я запускаю свое приложение без графического интерфейса или даже с минимизированным графическим интерфейсом, оно работает нормально каждый раз. Я вижу свои сообщения журнала в консоли (либо в командной строке, либо spyder
).
Если я запускаю одно и то же приложение без сворачивания графического интерфейса, я увижу сообщения журнала в графическом интерфейсе для инициализации и некоторых первых частей многопоточного процесса, но затем оно будет зависать в случайное время. Нет сообщения об ошибке, и использование ЦП, по-видимому, максимально для одного используемого ядра. Я включил блокировку, чтобы убедиться, что logging
не поступает из разных потоков, но это также не помогло.
Я пытался перейти на QPlainTextEdit
и QListWidget
, но каждый раз получаю одну и ту же проблему.
Кто-нибудь имеет представление о том, почему этот элемент графического интерфейса может привести к зависанию всего интерпретатора Python при просмотре и регистрации в нем сообщений?