使用 PySide2 关闭事件时来自 socketserver 的 ValueError

ValueError from socketserver on close event using PySide2

前几天我在尝试找出一种方法将数据发送到已经 运行 的 PyQt 实例时发现了这个 ,它运行良好,但我只是在摆弄 PySide2 和尝试了代码,关闭时出现错误。它在 PyQt5 上工作得很好,但在关闭 PySide 和 PySide2 时会出现相同的错误。有谁知道这是为什么?它说这是一个 ValueError 但我无法弄清楚。我正在使用 Python 3.6.

Client.py

import socket
IP, PORT = '127.0.0.1', 62236

def send(data):
    SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    SOCKET.connect((IP, PORT))
    SOCKET.send(data)
    SOCKET.close()

test_text = b'testing'
send(test_text)

Server.py PyQt5

import socketserver as SocketServer
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

IP, PORT = '127.0.0.1', 62236
app = QApplication([])

class Emitter(QObject):
    signal = pyqtSignal(str)

class Handler(SocketServer.BaseRequestHandler):
    emitter = Emitter()

    def handle(self):
        self.emitter.signal.emit(self.request.recv(1024).decode('utf-8'))

class Thread(QThread):
    def __init__(self, target, parent=None):
        QThread.__init__(self, parent)
        self.target = target

    def run(self):
        while True:
            self.target()

class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        Handler.emitter.signal.connect(self.onEmit)
        self.server = SocketServer.TCPServer((IP, PORT), Handler)
        thread = Thread(target=self.server.handle_request)
        thread.start()
        self.setLayout(QVBoxLayout())
        self.label = QLabel('somewhere over the rainbow')
        self.layout().addWidget(self.label)
        self.show()

    def closeEvent(self, event):
        self.server.server_close()
        event.accept()

    def onEmit(self, arg):
        self.label.setText(str(arg))

dialog = Dialog()
app.exec_()

Server.py PySide2

import socketserver as SocketServer
from PySide2.QtWidgets import *
from PySide2.QtCore import *

IP, PORT = '127.0.0.1', 62236
app = QApplication([])

class Emitter(QObject):
    signal = Signal(str)

class Handler(SocketServer.BaseRequestHandler):
    emitter = Emitter()

    def handle(self):
        self.emitter.signal.emit(self.request.recv(1024).decode('utf-8'))

class Thread(QThread):
    def __init__(self, target, parent=None):
        QThread.__init__(self, parent)
        self.target = target

    def run(self):
        while True:
            self.target()

class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        Handler.emitter.signal.connect(self.onEmit)
        self.server = SocketServer.TCPServer((IP, PORT), Handler)
        thread = Thread(target=self.server.handle_request)
        thread.start()
        self.setLayout(QVBoxLayout())
        self.label = QLabel('somewhere over the rainbow')
        self.layout().addWidget(self.label)
        self.show()

    def closeEvent(self, event):
        self.server.server_close()
        event.accept()

    def onEmit(self, arg):
        self.label.setText(str(arg))

dialog = Dialog()
app.exec_()

这里是错误。

Traceback (most recent call last):
  File "C:/Users/Rich/PycharmProjects/TestProject/Server.py", line 76, in run
    self.target()
  File "C:\python36\lib\socketserver.py", line 292, in handle_request
    selector.register(self, selectors.EVENT_READ)
  File "C:\python36\lib\selectors.py", line 299, in register
    key = super().register(fileobj, events, data)
  File "C:\python36\lib\selectors.py", line 237, in register
    key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
  File "C:\python36\lib\selectors.py", line 224, in _fileobj_lookup
    return _fileobj_to_fd(fileobj)
  File "C:\python36\lib\selectors.py", line 41, in _fileobj_to_fd
    raise ValueError("Invalid file descriptor: {}".format(fd))
ValueError: Invalid file descriptor: -1

问题已解决。不得不用

终止线程
self.thread.terminate()

在调用

之前
self.server.server_close()