[英]PYQt5: QThread: Destroyed while thread is still running ( with instance assigned as QDialog )
我遇到了這個問題 QThread: Destroyed while thread is still running 當我關閉NextWindow QDialog 時。
我寫的代碼是
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
from pathlib import Path
from hashlib import sha1
def recursive_hashes(path):
"""Generate name and SHA1 hash of all files under the given path"""
if path.is_file():
sha1_obj = sha1()
try:
with open(path, 'rb') as handle:
while True:
data = handle.read(8192)
if not data:
break
sha1_obj.update(data)
sha1_hash = sha1_obj.hexdigest()
except PermissionError:
sha1_hash = 'Permission Denied'
yield (str(path), sha1_hash)
elif path.is_dir():
try:
for child in path.iterdir():
yield from recursive_hashes(child)
except PermissionError:
yield(str(path), 'Permission Denied')
else:
yield (str(path), 'Not a file or dir')
class Worker(qtc.QObject):
hashed = qtc.pyqtSignal(str, str)
@qtc.pyqtSlot(str)
def hash_directory(self, root):
hash_gen = recursive_hashes(Path(root))
for path, sha1_hash in hash_gen:
self.hashed.emit(path, sha1_hash)
class NextWindow(qtw.QDialog):
hash_requested = qtc.pyqtSignal(str)
def __init__(self):
"""MainWindow constructor."""
super().__init__()
layout = qtw.QFormLayout()
self.setLayout(layout)
self.file_root = qtw.QLineEdit(returnPressed=self.start_hashing)
self.go_button = qtw.QPushButton('Start Hashing', clicked=self.start_hashing)
self.results = qtw.QTableWidget(0, 2)
self.results.setHorizontalHeaderLabels(['Name', 'SHA1-sum'])
self.results.horizontalHeader().setSectionResizeMode(qtw.QHeaderView.Stretch)
self.results.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
layout.addRow(qtw.QLabel('SHA1 Recursive Hasher'))
layout.addRow('File Root', self.file_root)
layout.addRow('', self.go_button)
layout.addRow(self.results)
# Create a worker object and a thread
self.worker = Worker()
self.worker_thread = qtc.QThread(self)
self.worker.hashed.connect(self.add_hash_to_table)
self.hash_requested.connect(self.worker.hash_directory)
# Assign the worker to the thread and start the thread
self.worker.moveToThread(self.worker_thread)
self.worker_thread.start()
# Connect signals & slots AFTER moving the object to the thread
# End main UI code
self.show()
def add_hash_to_table(self, name, sha1_sum):
"""Add the given name and sha1 sum to the table"""
row = self.results.rowCount()
self.results.insertRow(row)
self.results.setItem(row, 0, qtw.QTableWidgetItem(name))
self.results.setItem(row, 1, qtw.QTableWidgetItem(sha1_sum))
print(name, sha1_sum)
def start_hashing(self):
"""Prepare the GUI and emit the hash_requested signal"""
# Clear the table
while self.results.rowCount() > 0:
self.results.removeRow(0)
# Get the file root and validate it
file_root = self.file_root.text()
if not Path(file_root).exists():
qtw.QMessageBox.critical(self, 'Invalid Path', 'The specified file root does not exist.')
return
# Emit the signal
self.hash_requested.emit(file_root)
#self.worker.hash_directory(file_root)
class MainWindow(qtw.QDialog):
def __init__(self):
super().__init__()
layout = qtw.QFormLayout()
self.next_button = qtw.QPushButton('Next', clicked=self.next_button)
layout.addWidget(self.next_button)
self.setLayout(layout)
def next_button(self):
dialog = NextWindow()
dialog.exec_()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec())
我已經檢查了PyQt5 - QThread: Destroyed while thread is still running 和QThread: Destroyed while thread is still running 中的參考答案。
答案基本上沒有像 QThread 這樣分配實例
self.thread = QThread(parent=self) 雖然我這樣做了,但問題仍然存在。
QThread: Destroyed while thread is still running的調試消息可能無處不在,但原因可能並不總是相同。 對於這種情況,當您關閉對話框時,即使您將 self 作為
self.worker_thread = qtc.QThread(self)
在這種情況下,您應該拒絕 Qthread,如在 QDialog reject() 上優雅地終止 QThread問題中所述
所以你應該在你的代碼中再添加一行
self.worker_thread.start()
self.rejected.connect(self.thread.terminate)
根據PYQT5 文檔
When the thread is terminated, all threads waiting for the thread to finish will be woken up.
Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.
所以我建議添加
self.rejected.connect(self.thread.quit)
或者
self.rejected.connect(self.thread.exit)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.