我试图使用PySide和pySerial来创建一个与串口交互的跨平台应用程序。我最初使用Qtimers来轮询串行数据,但是这给cpu带来了很大的负担。所以我一直在尝试使用线程。
不幸的是,使用线程会导致Qt或pySerial陷入Segfault。
我已经尝试了python线程和QThreads,同样的问题,它发生在OSX,Windows 8和Ubuntu 12.04上。使用python 2.7和Qt4
This question seemed to have a similar problem, here:
this thread also seems to be a similar problem
下面是一个重新创建问题的小应用
#! /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来触发段错误,有时单个字符会触发它......
我不确定如何进一步调试这个......
所有帮助表示赞赏!!!!!!
我用不同的方法重新创建了问题,并在Qt community forum上提出了同样的问题
答案 0 :(得分:2)
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_terminal的签名为:
def write_terminal(text):
ui.plain_edit.appendPlainText(text)