我正在尝试为我的pyside gui构建一个.app,当我使用信号在主线程和另一个线程之间进行通信时,我遇到了问题。当我运行python代码时,一切正常。只有当我使用从pyinstaller构建的.app时才会出现此问题。
项目非常大,所以很难包含任何代码,所以我会尝试解释我在做什么。
我的第二个线程用于从控制我们设备的dylib调用某些函数。主线程使用回调告诉dylib停止它正在做的事情。 dylib在循环中调用回调函数,如果从主线程返回的值不是0,则停止。
正如我所提到的,当我运行Python代码(在Windows,Ubuntu,Mac下)时,它完美无缺。但是当使用使用pyinstaller构建的.app时,看起来信号不是从主线程发送的。在调试时,我打印了东西并最终看到dylib没有从回调中接收返回的值。 dylib确实使用了回调,我可以在主线程中看到预期的数据。
那么为什么信号不会被冻结的python代码触发? 有没有人遇到类似的问题? 如果你能给我一些调试建议,那真的很有帮助吗?
修改
我设法写了一个很小的代码来重现问题。当我运行python代码时,按“确定”,然后按“取消”,在窗口小部件中设置消息“DLL获取值”。使用Pyinstaller冻结代码时,在mac下,永远不会在窗口小部件上设置消息。在Windows 7上,一切都很好。
修改
实际上,共享库不需要导致问题。只有Python代码才会出现此问题。
这是Python代码:
import sys
from PySide import QtGui
from PySide.QtCore import QThread, Signal, QObject
def functionInDLL(callback):
return_value = 0
while (return_value == 0):
return_value = callback(2)
class MyThread(QThread):
str_signal = Signal(str)
def __init__(self):
QThread.__init__(self)
self.return_value = 0
def returnValueToDll(self, data=0):
return self.return_value
def run(self):
if functionInDLL(self.returnValueToDll) == 42:
print"DLL got the value."
self.str_signal.emit("DLL got the value.")
else:
print"DLL did not get the value."
self.str_signal.emit("DLL did not get the value.")
self.exec_()
def setValueSentToDll(self, data):
self.return_value = data
class MainThreadClass(QObject):
int_signal = Signal(int)
def __init__(self):
super(MainThreadClass, self).__init__()
self.test_thread = MyThread()
self.int_signal.connect(self.test_thread.setValueSentToDll)
def startMyThread(self):
self.test_thread.start()
def sendStopValueToDLL(self):
self.int_signal.emit(42)
class MyGUI(QtGui.QWidget):
def __init__(self):
super(MyGUI, self).__init__()
self.text_information = QtGui.QLabel(text="No started yet...")
self.dll_information = QtGui.QLabel(text="")
self.ok_button = QtGui.QPushButton("OK")
self.cancel_button = QtGui.QPushButton("Cancel")
self.close_button = QtGui.QPushButton("Close")
label_hbox = QtGui.QHBoxLayout()
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.ok_button)
hbox.addWidget(self.cancel_button)
hbox.addWidget(self.close_button)
vbox = QtGui.QVBoxLayout()
label_hbox.addWidget(self.text_information)
label_hbox.addWidget(self.dll_information)
vbox.addLayout(label_hbox)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.ok_button.clicked.connect(self.onOk)
self.cancel_button.clicked.connect(self.onCancel)
self.close_button.clicked.connect(self.onClose)
self.show()
self.main_thread = MainThreadClass()
self.main_thread.test_thread.str_signal.connect(lambda data: self.setDllStatusOnWidget(data))
def onOk(self):
self.main_thread.startMyThread()
self.text_information.setText("Started")
self.dll_information.setText("")
def onCancel(self):
self.main_thread.sendStopValueToDLL()
self.text_information.setText("Canceled")
def onClose(self):
self.main_thread.test_thread.exit()
self.close()
def setDllStatusOnWidget(self, text=""):
self.dll_information.setText(text)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = MyGUI()
sys.exit(app.exec_())
由于 使用Python2.7,Mac Pro Yosemite
答案 0 :(得分:0)
感谢codewarrior,我的错误得到了解决。 当我更换线路时:
self.main_thread.test_thread.str_signal.connect(lambda data: self.setDllStatusOnWidget(data))
通过这一行,删除lambda:
self.main_thread.test_thread.str_signal.connect(self.setDllStatusOnWidget)
有关详细信息,请参阅链接。我希望这可以帮助其他人。 pyinstaller_issue