PyQt5:线程仍在时被销毁运行
PyQt5 : Destroyed while thread is still running
试图添加异常,当服务器断开连接时,程序(客户端)应该做什么。
这个想法很简单。如果服务器关闭 - 客户端应尝试连接到服务器,直到服务器打开。
当服务器关闭时 - 程序尝试连接。但是当我打开服务器时,客户端已连接,然后连接断开,在客户端应用程序中我看到了 - QThread: Destroyed while thread is still 运行
这是我想要的简单示例(客户端的最小可重现示例):
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import socket
class ListeningThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(str)
def __init__(self, server_socket, parent=None):
QtCore.QThread.__init__(self, parent)
self.server_socket = server_socket
self.message = None
def run(self):
try:
while True:
self.message = self.server_socket.recv(4096)
self.mysignal.emit(self.message.decode('utf-8'))
except:
Push()
class Push(QtWidgets.QMainWindow):
def __init__(self):
super(Push, self).__init__()
print('now connecting...')
self.connect_server()
def connect_server(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.server_socket.connect(('127.0.0.1', 5555))
self.message_monitor = ListeningThread(self.server_socket)
self.message_monitor.mysignal.connect(self.init_UI)
self.message_monitor.start()
except:
Push()
def init_UI(self, message):
print(message)
app =QtWidgets.QApplication([])
application = Push()
sys.exit(app.exec_())
我在 ListeningThread 中尝试过:
class ListeningThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(str)
def __init__(self, server_socket, parent=None):
QtCore.QThread.__init__(self, parent)
self.server_socket = server_socket
self.message = None
def run(self):
try:
while not self.isInterruptionRequested():
self.message = self.server_socket.recv(4096)
self.mysignal.emit(self.message.decode('utf-8'))
except:
print('error in thread')
self.requestInterruption()
self.wait()
Push()
但是问题还是一样。
我想我应该在 Push.connect_server 开始之前关闭线程,但不知道如何。
对于最小的可重现示例,您可以使用该服务器:
import socket
import threading
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 5555))
server_socket.listen()
clients = []
def accept_socket():
while True:
client_socket, addr = server_socket.accept()
print(f'connection from {addr}')
print(client_socket)
if client_socket not in clients:
clients.append(client_socket)
def sending_message(clients, data):
for client_socket in clients:
try:
client_socket.send(data.encode("utf-8"))
except:
pass
accept_thread = threading.Thread(target= accept_socket)
accept_thread.start()
while True:
data = input('Enter_message:\n')
sending_message(clients, data)
问题是,当发生异常时,您正在创建一个新的“Push”对象,该对象的范围有限,因为它是一个局部变量,所以它会被销毁,线程等对象也会被销毁,这就是它所表明的。错误信息。
您可以使用 QTcpSocket 来通过信号以简单的方式处理套接字并使用 Qt 事件循环,而不是让您的生活因线程处理而变得复杂(IMO 它们是最后的选择)。
from functools import cached_property
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
class Client(QtCore.QObject):
messageChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.socket.stateChanged.connect(self.handle_state_changed)
self.socket.errorOccurred.connect(self.handle_error_occurred)
self.socket.readyRead.connect(self.handle_ready_read)
@cached_property
def socket(self):
return QtNetwork.QTcpSocket()
def try_connect(self):
self.socket.connectToHost("127.0.0.1", 5555)
def handle_state_changed(self, state):
print(f"state: {state}")
if state == QtNetwork.QAbstractSocket.UnconnectedState:
print("disconnected")
QtCore.QTimer.singleShot(1000, self.try_connect)
elif state == QtNetwork.QAbstractSocket.ConnectedState:
print("connected")
def handle_error_occurred(self, error):
print(f"error code {error}, message: {self.socket.errorString()}")
def handle_ready_read(self):
codec = QtCore.QTextCodec.codecForName("UTF-8")
message = codec.toUnicode(self.socket.readAll())
self.messageChanged.emit(message)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.client.messageChanged.connect(self.handle_message_changed)
self.client.try_connect()
@cached_property
def client(self):
return Client()
def handle_message_changed(self, message):
print(f"client message: {message}")
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
试图添加异常,当服务器断开连接时,程序(客户端)应该做什么。
这个想法很简单。如果服务器关闭 - 客户端应尝试连接到服务器,直到服务器打开。
当服务器关闭时 - 程序尝试连接。但是当我打开服务器时,客户端已连接,然后连接断开,在客户端应用程序中我看到了 - QThread: Destroyed while thread is still 运行 这是我想要的简单示例(客户端的最小可重现示例):
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import socket
class ListeningThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(str)
def __init__(self, server_socket, parent=None):
QtCore.QThread.__init__(self, parent)
self.server_socket = server_socket
self.message = None
def run(self):
try:
while True:
self.message = self.server_socket.recv(4096)
self.mysignal.emit(self.message.decode('utf-8'))
except:
Push()
class Push(QtWidgets.QMainWindow):
def __init__(self):
super(Push, self).__init__()
print('now connecting...')
self.connect_server()
def connect_server(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.server_socket.connect(('127.0.0.1', 5555))
self.message_monitor = ListeningThread(self.server_socket)
self.message_monitor.mysignal.connect(self.init_UI)
self.message_monitor.start()
except:
Push()
def init_UI(self, message):
print(message)
app =QtWidgets.QApplication([])
application = Push()
sys.exit(app.exec_())
我在 ListeningThread 中尝试过:
class ListeningThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(str)
def __init__(self, server_socket, parent=None):
QtCore.QThread.__init__(self, parent)
self.server_socket = server_socket
self.message = None
def run(self):
try:
while not self.isInterruptionRequested():
self.message = self.server_socket.recv(4096)
self.mysignal.emit(self.message.decode('utf-8'))
except:
print('error in thread')
self.requestInterruption()
self.wait()
Push()
但是问题还是一样。 我想我应该在 Push.connect_server 开始之前关闭线程,但不知道如何。
对于最小的可重现示例,您可以使用该服务器:
import socket
import threading
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 5555))
server_socket.listen()
clients = []
def accept_socket():
while True:
client_socket, addr = server_socket.accept()
print(f'connection from {addr}')
print(client_socket)
if client_socket not in clients:
clients.append(client_socket)
def sending_message(clients, data):
for client_socket in clients:
try:
client_socket.send(data.encode("utf-8"))
except:
pass
accept_thread = threading.Thread(target= accept_socket)
accept_thread.start()
while True:
data = input('Enter_message:\n')
sending_message(clients, data)
问题是,当发生异常时,您正在创建一个新的“Push”对象,该对象的范围有限,因为它是一个局部变量,所以它会被销毁,线程等对象也会被销毁,这就是它所表明的。错误信息。
您可以使用 QTcpSocket 来通过信号以简单的方式处理套接字并使用 Qt 事件循环,而不是让您的生活因线程处理而变得复杂(IMO 它们是最后的选择)。
from functools import cached_property
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
class Client(QtCore.QObject):
messageChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.socket.stateChanged.connect(self.handle_state_changed)
self.socket.errorOccurred.connect(self.handle_error_occurred)
self.socket.readyRead.connect(self.handle_ready_read)
@cached_property
def socket(self):
return QtNetwork.QTcpSocket()
def try_connect(self):
self.socket.connectToHost("127.0.0.1", 5555)
def handle_state_changed(self, state):
print(f"state: {state}")
if state == QtNetwork.QAbstractSocket.UnconnectedState:
print("disconnected")
QtCore.QTimer.singleShot(1000, self.try_connect)
elif state == QtNetwork.QAbstractSocket.ConnectedState:
print("connected")
def handle_error_occurred(self, error):
print(f"error code {error}, message: {self.socket.errorString()}")
def handle_ready_read(self):
codec = QtCore.QTextCodec.codecForName("UTF-8")
message = codec.toUnicode(self.socket.readAll())
self.messageChanged.emit(message)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.client.messageChanged.connect(self.handle_message_changed)
self.client.try_connect()
@cached_property
def client(self):
return Client()
def handle_message_changed(self, message):
print(f"client message: {message}")
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()