Я пытаюсь разработать многопоточную программу с интерфейсом TUI. В основном у меня есть основной L oop, решающий, что делать, и некоторые задачи (такие как TUI или чтение данных из очереди и их обработка) выполняются в отдельном потоке. Мой TUI использует curses и является производным от потока классом, который выглядит следующим образом (для ясности я удалил несущественный код):
import threading
from time import sleep
import curses
import logging
from curses.textpad import Textbox, rectangle
from datetime import datetime
import re
from curses import panel
import os
import sys
class GenericTUI(threading.Thread):
def __init__(self, logger=logging.getLogger()):
threading.Thread.__init__(self,name="genericTUI" + str(os.getpid()), daemon=True)
self.keyPressedList = list()
self.alive = True
self._myStdscr = None
self.title = ""
self.logger = logger
self.lock = threading.Lock()
def run(self):
curses.wrapper(self.main)
curses.nocbreak()
curses.echo()
curses.noraw()
sys.exit(0)
def main(self,stdscr):
self._myStdscr = stdscr
self._myStdscr.nodelay(True)
self._myStdscr.keypad(True)
self._myStdscr.box()
while self.alive:
sleep(0.4)
try :
key = self._myStdscr.getkey()
if re.match('[A-Z_\+\-\*/]', key):
self.keyPressedList.append(key)
except Exception as e:
## ignoring no key presssed
pass
try :
with self.lock :
self._myStdscr.clear()
self._myStdscr.addstr(1, 2, str(datetime.now())+" "+ sys.argv[0] +" "+self.title )
### printing other things
self._myStdscr.refresh()
except Exception as e:
self.logger.error(e, exc_info=True)
continue
self._myStdscr.clear()
self._myStdscr.keypad(0)
def getKeyPressed(self):
if self.keyPressedList :
return self.keyPressedList.pop()
else :
return None
def stop(self):
self.alive = False
def updateTitle(self,title):
with self.lock : self.title = title
if __name__ == "__main__":
## the main is used for some test when the lib is called directly
testGUI = GenericTUI()
alive = True
testGUI.logger.addHandler(logging.StreamHandler())
testGUI.logger.setLevel(logging.DEBUG)
testGUI.start()
while alive :
testGUI.updateTitle('title %s'%str(datetime.now() ))
k = testGUI.getKeyPressed()
if k is not None:
if k=='Q' :
alive = False
else :
testGUI.addMessage('unknown key %s'%k , maj=True)
sleep(0.1)
основной l oop моей программы, создающей экземпляр и запускающей объект genericTUI и получить от него нажатие клавиши или установить значение для отображения.
Но когда я закрываю программу, мой терминал находится в смешном состоянии, даже если я использовал функцию-оболочку curses или попытался выполнить сброс вручную с помощью curses.nocbreak () и другие.
Я не могу понять, что я сделал не так? Я ошибаюсь, используя проклятия внутри потока?