ValueError от socketserver при событии закрытия с использованием PySide2 - PullRequest
0 голосов
/ 03 июня 2018

Я нашел этот ответ на днях, когда пытался выяснить способ отправки данных в уже запущенный экземпляр 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

1 Ответ

0 голосов
/ 05 июня 2018

Проблема решена.Пришлось завершить поток с помощью

self.thread.terminate()

перед вызовом

self.server.server_close()
...