简体   繁体   中英

ValueError from socketserver on close event using PySide2

I found this answer the other day when trying to figure out a way to send data to an already running instance of PyQt and it works well but I was just messing around with PySide2 and tried the code and it gives an error when closing. It works completely fine with PyQt5 but it gives the same error on closing with PySide and PySide2. Anyone know why that is? It says it's a ValueError but I can't figure it out. I am using 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_()

Here is the error.

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

Problem solved. Had to terminate the thread with

self.thread.terminate()

before calling

self.server.server_close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM