Multithreading PySide、pySerial和线程导致SEGFULT
我正在尝试使用PySide和pySerial来制作一个与串口交互的跨平台应用程序。我最初使用qtimer轮询串行数据,但这给cpu带来了很大的负载。所以我一直在尝试使用线程 不幸的是,使用线程会导致Qt或pySerial出现故障 我试过python线程和QThreads,同样的问题,它发生在OSX、Windows8和Ubuntu12.04上。使用Python2.7和Qt4 下面是一个小应用程序,它重现了这个问题Multithreading PySide、pySerial和线程导致SEGFULT,multithreading,qt,segmentation-fault,pyside,pyserial,Multithreading,Qt,Segmentation Fault,Pyside,Pyserial,我正在尝试使用PySide和pySerial来制作一个与串口交互的跨平台应用程序。我最初使用qtimer轮询串行数据,但这给cpu带来了很大的负载。所以我一直在尝试使用线程 不幸的是,使用线程会导致Qt或pySerial出现故障 我试过python线程和QThreads,同样的问题,它发生在OSX、Windows8和Ubuntu12.04上。使用Python2.7和Qt4 下面是一个小应用程序,它重现了这个问题 #! /usr/bin/python import sys import ser
#! /usr/bin/python
import sys
import serial
import threading
from PySide import QtCore, QtGui, QtUiTools
class serial_port_class(object):
def __init__(self, ui):
self.ui = ui
self.connected = False
def __del__(self):
self.disconnect_port()
def connect_port(self):
try:
self.serial_port = serial.Serial("/dev/tty.usbmodem1451", 9600, timeout = None)
self.connected = True
except serial.SerialException, e:
self.connected = False
if self.connected:
self.serial_thread = threading.Thread(target=self.recieve_port, args=([self.ui]))
self.serial_thread.start()
def disconnect_port(self):
self.connected = False
self.serial_thread.join()
self.serial_port.close()
def recieve_port(self, ui):
while self.connected:
try:
text = self.serial_port.read(1)
if text != '':
ui.plain_edit.appendPlainText(text)
except serial.SerialException, e:
connected = False
class KeyPressEater(QtCore.QObject):
def eventFilter(self, obj, event):
global serial_port
if event.type() == QtCore.QEvent.KeyPress:
ch = event.text().encode('utf-8')
if serial_port.connected == True:
serial_port.serial_port.write(ch)
return QtCore.QObject.eventFilter(self, obj, event)
def main():
global serial_port
app = QtGui.QApplication(sys.argv)
ui = QtGui.QWidget()
ui.plain_edit = QtGui.QPlainTextEdit(ui)
keyFilter = KeyPressEater(ui)
ui.plain_edit.installEventFilter(keyFilter)
serial_port = serial_port_class(ui)
serial_port.connect_port()
ui.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
有时需要一点数据IO来触发segfault,有时一个字符就会触发它
我真的不确定如何进一步调试这个
感谢所有的帮助
更新
我用不同的硬盘重新创建了这个问题,并在Qt对象不是线程安全的,所以调用
ui.plain_edit.appendPlainText(text)
从另一个线程是坏的
解决这个问题的一种方法是使用QThreads和内置的线程安全消息和事件系统
比如:
class receivePort(QThread):
message = QtCore.Signal(str)
def __init__(self):
self.connected = False
QThread.__init__(self)
def run(self):
while self.connected:
try:
text = self.serial_port.read(1)
if text != '':
self.message.emit(text)
except serial.SerialException, e:
connected = False
并使用以下方法将其连接起来:
serial_thread = receivePort()
serial_thread.message.connect(write_terminal, QtCore.Qt.QueuedConnection)
serial_thread.start()
其中,write_终端具有以下签名:
def write_terminal(text):
ui.plain_edit.appendPlainText(text)
如果您正在使用Qt,是否有任何原因不使用QtSerialPort?不确定pyside是否有绑定,尽管添加起来应该很容易。您是正确的,pyside没有QtSerialPort的绑定。我对解决这种情况比自己添加QtSerialPort绑定更感兴趣。由于其他人似乎也有类似的问题,我认为追踪原因并可能向任何一个项目提交错误报告都是有价值的。