文章目录
问题分析
运行以下程序:
python
def run_thread_WTD(self):
threading.Thread(target=self.WTD).start()
def WTD(self):
word_path = self.word_path.text()
# textBrowser为多行文本框QTextEdit
self.pycorrectorKenlm(word_path, textBrowser)
# kenlm
def pycorrectorKenlm(self, word_path, textBrowser):
error_counter_kenlm = 0
try:
m = Corrector(language_model_path='zh_giga.no_cna_cmn.prune01244.klm',
custom_confusion_path_or_dict='my_custom_confusion.txt')#./ means current Path
except:
textBrowser.append("Error")
doc = docx.Document(word_path)
for para in doc.paragraphs:
if (para.text == ""):
pass
else:
if (len(m.correct_batch([para.text])[0]['errors']) == 0):
pass
else:
error_counter_kenlm += 1
json_data = json.dumps(m.correct_batch([para.text])[0], sort_keys=False, indent=4, ensure_ascii=False)
textBrowser.append(json_data)
json_data_1 = json.loads(json_data)
self.sourses = jsonpath(json_data_1, '$..source')
self.targets = jsonpath(json_data_1, '$..target')
textBrowser.append("\n")
textBrowser.append(f"Chinese Total error: {error_counter_kenlm}")
运行后,PyQt主窗口界面卡死,一段时间后异常退出:
python
进程已结束,退出代码 -1073741819 (0xC0000005)
通过测试分析,发现出现异常的可能的原因:对于耗时长的函数,当采用多线程编程调用其函数,如果支线程频繁访问了界面对象可能会导致界面卡死,异常退出。
(在以上例子中,函数pycorrectorKenlm
就不断的在访问界面对象textBrowser
从而导致界面卡死。)
通过测试,发现在线程调用的函数(例:WTD
)(包括线程调用的函数中所调用的函数)都不能频繁访问界面对象,否则可能会导致界面卡死,异常退出。
解决方法
以上述代码为例,将支线程中访问的界面对象去除,用一个临时变量保存数据,最终返回数据结果,同时编写一个QTimer
函数,对返回的数据结果进行判断,返回值不为空,则在textBrowser
中打印数据。(相当于开启两个线程)
修改后的程序:
python
def run_thread_WTD(self):
self.process_info = []
self.timer1.start(1000)
threading.Thread(target=self.WTD).start()
def WTD(self):
word_path = self.word_path.text()
# textBrowser为多行文本框QTextEdit
self.process_info = self.pycorrectorKenlm(word_path)
def write_result_text(self):
if self.process_info != []:
for i in self.process_info:
self.result_text.append(i)
self.timer1.stop()
self.process_info = []
def pycorrectorKenlm(self, word_path):
process_info = []
error_counter_kenlm = 0
try:
m = Corrector(language_model_path='zh_giga.no_cna_cmn.prune01244.klm',
custom_confusion_path_or_dict='my_custom_confusion.txt')#./ means current Path
except:
process_info.append("Error")
doc = docx.Document(word_path)
for para in doc.paragraphs:
if (para.text == ""):
pass
else:
if (len(m.correct_batch([para.text])[0]['errors']) == 0):
pass
else:
error_counter_kenlm += 1
json_data = json.dumps(m.correct_batch([para.text])[0], sort_keys=False, indent=4, ensure_ascii=False)
process_info.append(json_data)
j son_data_1 = json.loads(json_data)
self.sourses = jsonpath(json_data_1, '$..source')
self.targets = jsonpath(json_data_1, '$..target')
process_info.append("\n")
process_info.append(f"Chinese Total error: {error_counter_kenlm}")